@lvl99dotcom/paintcanvas 0.4.0 → 0.6.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/README.md +30 -15
- package/dist/lib/brushes/configRanges/index.d.ts +17 -0
- package/dist/lib/brushes/configRanges/index.js +31 -1
- package/dist/lib/brushes/params/index.d.ts +2 -1
- package/dist/lib/brushes/params/index.js +7 -4
- package/dist/lib/brushes/presets/round/index.d.ts +1 -1
- package/dist/lib/brushes/presets/round/index.js +12 -7
- package/dist/lib/brushes/presets/square/index.d.ts +1 -1
- package/dist/lib/brushes/presets/square/index.js +7 -3
- package/dist/lib/brushes/shapeImage/index.d.ts +7 -3
- package/dist/lib/brushes/shapeImage/index.js +15 -9
- package/dist/lib/brushes/shapes/index.d.ts +18 -0
- package/dist/lib/brushes/shapes/index.js +86 -0
- package/dist/lib/brushes/types/index.d.ts +8 -0
- package/dist/lib/classes/BrushSettings/index.d.ts +29 -2
- package/dist/lib/classes/BrushSettings/index.js +51 -14
- package/dist/lib/classes/KeyboardShortcuts/index.d.ts +31 -2
- package/dist/lib/classes/KeyboardShortcuts/index.js +66 -4
- package/dist/lib/classes/Layer/index.d.ts +10 -0
- package/dist/lib/classes/Layer/index.js +15 -1
- package/dist/lib/classes/LayerAutosave/index.d.ts +9 -15
- package/dist/lib/classes/LayerAutosave/index.js +30 -43
- package/dist/lib/classes/LayerStack/index.d.ts +15 -0
- package/dist/lib/classes/LayerStack/index.js +26 -2
- package/dist/lib/classes/PaintCanvas/index.d.ts +72 -3
- package/dist/lib/classes/PaintCanvas/index.js +106 -12
- package/dist/lib/classes/PngEncoder/index.d.ts +41 -0
- package/dist/lib/classes/PngEncoder/index.js +104 -0
- package/dist/lib/classes/ProfileGraphs/index.d.ts +87 -0
- package/dist/lib/classes/ProfileGraphs/index.js +148 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +3 -2
- package/dist/lib/classes/SettingsAutosave/index.js +6 -3
- package/dist/lib/classes/UiSettings/index.d.ts +68 -0
- package/dist/lib/classes/UiSettings/index.js +82 -0
- package/dist/lib/messages/schema.d.ts +720 -0
- package/dist/lib/presets/schema.d.ts +360 -0
- package/dist/lib/presets/schema.js +8 -1
- package/dist/lib/profiles/index.d.ts +61 -0
- package/dist/lib/profiles/index.js +131 -0
- package/dist/lib/profiles/schema.d.ts +73 -0
- package/dist/lib/profiles/schema.js +53 -0
- package/dist/lib/rendering/sample/index.d.ts +11 -0
- package/dist/lib/rendering/sample/index.js +36 -5
- package/dist/lib/settings/index.d.ts +2 -1
- package/dist/lib/settings/index.js +7 -2
- package/dist/lib/settings/schema.d.ts +67 -0
- package/dist/lib/settings/schema.js +20 -0
- package/dist/lib/validation/validators.generated.js +13191 -3655
- package/dist/locales/en-GB.js +39 -2
- package/dist/locales/en-US.js +39 -2
- package/dist/locales/fr.js +39 -2
- package/dist/locales/ja.js +39 -2
- package/dist/locales/ko.js +39 -2
- package/dist/locales/zh-Hans.js +39 -2
- package/dist/locales/zh-Hant.js +39 -2
- package/dist/package.js +1 -1
- package/dist/testing/recordingCanvas.js +2 -1
- package/dist/ui/ask/index.d.ts +48 -0
- package/dist/ui/ask/index.js +67 -0
- package/dist/ui/base/index.d.ts +10 -3
- package/dist/ui/base/index.js +19 -4
- package/dist/ui/dismiss/index.d.ts +21 -0
- package/dist/ui/dismiss/index.js +27 -0
- package/dist/ui/drag/index.d.ts +51 -0
- package/dist/ui/drag/index.js +81 -0
- package/dist/ui/elements/PaintCanvas/index.d.ts +17 -12
- package/dist/ui/elements/PaintCanvas/index.js +36 -17
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +6 -6
- package/dist/ui/elements/PcAppSettings/index.js +21 -65
- package/dist/ui/elements/PcBrushConfig/index.d.ts +34 -16
- package/dist/ui/elements/PcBrushConfig/index.js +263 -153
- package/dist/ui/elements/PcBrushConfig/style.js +1 -1
- package/dist/ui/elements/PcBrushSize/index.d.ts +53 -0
- package/dist/ui/elements/PcBrushSize/index.js +66 -0
- package/dist/ui/elements/PcBrushTest/index.d.ts +26 -0
- package/dist/ui/elements/PcBrushTest/index.js +79 -6
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcButton/index.d.ts +12 -3
- package/dist/ui/elements/PcButton/index.js +18 -10
- package/dist/ui/elements/PcCanvas/index.d.ts +27 -2
- package/dist/ui/elements/PcCanvas/index.js +63 -13
- package/dist/ui/elements/PcCanvas/style.js +1 -1
- package/dist/ui/elements/PcCanvasMap/style.js +1 -1
- package/dist/ui/elements/PcClipboardTools/index.d.ts +49 -0
- package/dist/ui/elements/PcClipboardTools/index.js +125 -0
- package/dist/ui/elements/PcContextMenu/index.d.ts +2 -2
- package/dist/ui/elements/PcDialog/index.d.ts +46 -10
- package/dist/ui/elements/PcDialog/index.js +102 -51
- package/dist/ui/elements/PcDialogWindow/index.d.ts +141 -0
- package/dist/ui/elements/PcDialogWindow/index.js +385 -0
- package/dist/ui/elements/PcInputSettings/index.d.ts +13 -0
- package/dist/ui/elements/PcInputSettings/index.js +16 -1
- package/dist/ui/elements/PcMenu/index.d.ts +48 -3
- package/dist/ui/elements/PcMenu/index.js +111 -19
- package/dist/ui/elements/PcNumberSlider/index.d.ts +137 -0
- package/dist/ui/elements/PcNumberSlider/index.js +247 -0
- package/dist/ui/elements/PcPane/index.d.ts +3 -1
- package/dist/ui/elements/PcPane/index.js +44 -7
- package/dist/ui/elements/PcPanel/index.d.ts +2 -2
- package/dist/ui/elements/PcPanel/index.js +8 -8
- package/dist/ui/elements/PcPanelBrushes/index.d.ts +5 -17
- package/dist/ui/elements/PcPanelBrushes/index.js +13 -48
- package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
- package/dist/ui/elements/PcPanelColours/index.js +2 -2
- package/dist/ui/elements/PcPanelColours/style.js +1 -1
- package/dist/ui/elements/PcPanelLayers/index.js +1 -1
- package/dist/ui/elements/PcPanelLayers/style.js +1 -1
- package/dist/ui/elements/PcPopover/index.d.ts +39 -1
- package/dist/ui/elements/PcPopover/index.js +72 -4
- package/dist/ui/elements/PcProfileEditor/index.d.ts +103 -0
- package/dist/ui/elements/PcProfileEditor/index.js +259 -0
- package/dist/ui/elements/PcProfileGraph/index.d.ts +84 -0
- package/dist/ui/elements/PcProfileGraph/index.js +317 -0
- package/dist/ui/elements/PcShortcutSettings/index.js +9 -13
- package/dist/ui/elements/PcSliderRange/index.d.ts +147 -0
- package/dist/ui/elements/PcSliderRange/index.js +307 -0
- package/dist/ui/elements/PcStats/index.d.ts +19 -4
- package/dist/ui/elements/PcStats/index.js +29 -13
- package/dist/ui/elements/PcThemePicker/index.d.ts +17 -15
- package/dist/ui/elements/PcThemePicker/index.js +22 -21
- package/dist/ui/elements/PcToolSettings/index.d.ts +48 -9
- package/dist/ui/elements/PcToolSettings/index.js +382 -318
- package/dist/ui/elements/PcToolSettings/style.js +1 -1
- package/dist/ui/elements/PcToolbar/index.d.ts +15 -0
- package/dist/ui/elements/PcToolbar/index.js +55 -14
- package/dist/ui/elements/PcToolbar/style.js +1 -1
- package/dist/ui/icons/images/icon-brush@2x.js +3 -0
- package/dist/ui/icons/images/icon-circle-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-clipboard@2x.js +3 -0
- package/dist/ui/icons/images/icon-cog@2x.js +3 -0
- package/dist/ui/icons/images/icon-cursor@2x.js +3 -0
- package/dist/ui/icons/images/icon-diagonal-tlbr-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-diagonal-trbl-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-eraser@2x.js +3 -0
- package/dist/ui/icons/images/icon-eyedropper@2x.js +3 -0
- package/dist/ui/icons/images/icon-flip-horizontal@2x.js +3 -0
- package/dist/ui/icons/images/icon-flip-vertical@2x.js +3 -0
- package/dist/ui/icons/images/icon-focus-pen@2x.js +3 -0
- package/dist/ui/icons/images/icon-freehand-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-hidden@2x.js +3 -0
- package/dist/ui/icons/images/icon-horizontal-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-layers@2x.js +3 -0
- package/dist/ui/icons/images/icon-linked@2x.js +3 -0
- package/dist/ui/icons/images/icon-locked@2x.js +3 -0
- package/dist/ui/icons/images/icon-moon@2x.js +3 -0
- package/dist/ui/icons/images/icon-pan@2x.js +3 -0
- package/dist/ui/icons/images/icon-polygon-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-pressure@2x.js +3 -0
- package/dist/ui/icons/images/icon-profile-graph@2x.js +3 -0
- package/dist/ui/icons/images/icon-randomise@2x.js +3 -0
- package/dist/ui/icons/images/icon-rectangle-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-redo@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate-90-left@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate-90-right@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-bezier-cubic@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-bezier-quad@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-linear@2x.js +3 -0
- package/dist/ui/icons/images/icon-star@2x.js +3 -0
- package/dist/ui/icons/images/icon-sun@2x.js +3 -0
- package/dist/ui/icons/images/icon-tilt@2x.js +3 -0
- package/dist/ui/icons/images/icon-undo@2x.js +3 -0
- package/dist/ui/icons/images/icon-unlinked@2x.js +3 -0
- package/dist/ui/icons/images/icon-unlocked@2x.js +3 -0
- package/dist/ui/icons/images/icon-vertical-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-visible@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom-in@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom-out@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom@2x.js +3 -0
- package/dist/ui/icons/index.d.ts +1 -1
- package/dist/ui/icons/index.js +86 -72
- package/dist/ui/index.d.ts +13 -3
- package/dist/ui/index.js +15 -4
- package/dist/ui/layout/index.d.ts +9 -1
- package/dist/ui/layout/index.js +11 -2
- package/dist/ui/styles/index.d.ts +21 -1
- package/dist/ui/styles/index.js +73 -14
- package/dist/ui/tokens/index.d.ts +5 -4
- package/dist/ui/tokens/index.js +12 -7
- package/locales/en-GB.json +39 -2
- package/locales/en-US.json +39 -2
- package/locales/fr.json +39 -2
- package/locales/ja.json +39 -2
- package/locales/ko.json +39 -2
- package/locales/zh-Hans.json +39 -2
- package/locales/zh-Hant.json +39 -2
- package/package.json +27 -18
- package/dist/ui/icons/images/brush.js +0 -3
- package/dist/ui/icons/images/circle-mask.js +0 -3
- package/dist/ui/icons/images/clipboard.js +0 -3
- package/dist/ui/icons/images/cursor.js +0 -3
- package/dist/ui/icons/images/eraser.js +0 -3
- package/dist/ui/icons/images/eyedropper.js +0 -3
- package/dist/ui/icons/images/flip-horizontal.js +0 -3
- package/dist/ui/icons/images/flip-vertical.js +0 -3
- package/dist/ui/icons/images/focus-pen.js +0 -3
- package/dist/ui/icons/images/freehand-mask.js +0 -3
- package/dist/ui/icons/images/hidden.js +0 -3
- package/dist/ui/icons/images/layers.js +0 -3
- package/dist/ui/icons/images/linked.js +0 -3
- package/dist/ui/icons/images/locked.js +0 -3
- package/dist/ui/icons/images/moon.js +0 -3
- package/dist/ui/icons/images/pan.js +0 -3
- package/dist/ui/icons/images/polygon-mask.js +0 -3
- package/dist/ui/icons/images/pressure.js +0 -3
- package/dist/ui/icons/images/randomise.js +0 -3
- package/dist/ui/icons/images/rectangle-mask.js +0 -3
- package/dist/ui/icons/images/redo.js +0 -3
- package/dist/ui/icons/images/rotate-90-left.js +0 -3
- package/dist/ui/icons/images/rotate-90-right.js +0 -3
- package/dist/ui/icons/images/smoothing-bezier-cubic.js +0 -3
- package/dist/ui/icons/images/smoothing-bezier-quad.js +0 -3
- package/dist/ui/icons/images/smoothing-linear.js +0 -3
- package/dist/ui/icons/images/star.js +0 -3
- package/dist/ui/icons/images/sun.js +0 -3
- package/dist/ui/icons/images/tilt.js +0 -3
- package/dist/ui/icons/images/undo.js +0 -3
- package/dist/ui/icons/images/unlinked.js +0 -3
- package/dist/ui/icons/images/unlocked.js +0 -3
- package/dist/ui/icons/images/visible.js +0 -3
- package/dist/ui/icons/images/zoom-in.js +0 -3
- package/dist/ui/icons/images/zoom-out.js +0 -3
- package/dist/ui/icons/images/zoom.js +0 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PcElement, defineElement } from "../../base/index.js";
|
|
2
|
+
import ChangeController from "../../ChangeController/index.js";
|
|
3
|
+
import "../PcNumberSlider/index.js";
|
|
4
|
+
import { BRUSH_SIZE_STEP } from "../../../lib/classes/BrushSettings/index.js";
|
|
5
|
+
import { css, html, nothing } from "lit";
|
|
6
|
+
import { live } from "lit/directives/live.js";
|
|
7
|
+
// src/ui/elements/PcBrushSize/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* A brush's size as text: one number when the width and height are the same, otherwise "width × height".
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* sizeText({ width: 20, height: 20 }); // "20"
|
|
13
|
+
* sizeText({ width: 30, height: 10 }); // "30 × 10"
|
|
14
|
+
*/
|
|
15
|
+
var sizeText = ({ width, height }) => width === height ? String(width) : `${width} × ${height}`;
|
|
16
|
+
/**
|
|
17
|
+
* A brush or eraser's size, as a `pc-number-slider`: pressed and dragged right or up it gets bigger, left or down
|
|
18
|
+
* smaller, keeping its proportions (see `BrushSettings.resize`). Tapping it lets you type the larger side's size. With
|
|
19
|
+
* keyboard focus, the arrow keys change it by a pixel and Page Up and Page Down by a step (like `]` and `[`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* html`<pc-brush-size .settings=${app.brush} label="Brush size"></pc-brush-size>`
|
|
23
|
+
*/
|
|
24
|
+
var PcBrushSize = class extends PcElement {
|
|
25
|
+
static properties = {
|
|
26
|
+
...PcElement.properties,
|
|
27
|
+
settings: { attribute: false },
|
|
28
|
+
label: { type: String }
|
|
29
|
+
};
|
|
30
|
+
static styles = [PcElement.styles, css`
|
|
31
|
+
:host {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
}
|
|
34
|
+
pc-number-slider {
|
|
35
|
+
flex: 1;
|
|
36
|
+
}
|
|
37
|
+
`];
|
|
38
|
+
changes = new ChangeController(this, () => [this.settings]);
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
this.label = "";
|
|
42
|
+
}
|
|
43
|
+
/** Resize to the slider's value (the larger side), keeping the proportions */
|
|
44
|
+
onChange(event) {
|
|
45
|
+
const settings = this.settings;
|
|
46
|
+
settings.resize(event.detail.value - settings.largerSide);
|
|
47
|
+
this.requestUpdate();
|
|
48
|
+
}
|
|
49
|
+
render() {
|
|
50
|
+
const settings = this.settings;
|
|
51
|
+
if (!settings) return nothing;
|
|
52
|
+
const larger = settings.largerSide;
|
|
53
|
+
return html`<pc-number-slider
|
|
54
|
+
exportparts="control, field"
|
|
55
|
+
min=${1}
|
|
56
|
+
max=${256}
|
|
57
|
+
page-step=${Math.max(1, Math.round(larger * BRUSH_SIZE_STEP))}
|
|
58
|
+
label=${this.label}
|
|
59
|
+
.value=${live(larger)}
|
|
60
|
+
.text=${sizeText(settings)}
|
|
61
|
+
@pc-change=${this.onChange}
|
|
62
|
+
></pc-number-slider>`;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
defineElement("pc-brush-size", PcBrushSize);
|
|
66
|
+
export { PcBrushSize, sizeText };
|
|
@@ -8,9 +8,18 @@ export declare const TEST_AREA_WIDTH = 800;
|
|
|
8
8
|
export declare const TEST_AREA_HEIGHT = 320;
|
|
9
9
|
/** The colour test strokes are drawn in, whatever the current colour */
|
|
10
10
|
export declare const TEST_COLOUR = "#000000";
|
|
11
|
+
/** The colour of the circles showing a stroke's sampled points, while stroke points are shown */
|
|
12
|
+
export declare const POINT_COLOUR = "#e8175d";
|
|
13
|
+
/** The colour of the dots showing where a stroke placed its stamps, while stroke points are shown */
|
|
14
|
+
export declare const STAMP_COLOUR = "#1e88e5";
|
|
15
|
+
/** How long a finished stroke's points stay shown (milliseconds) */
|
|
16
|
+
export declare const STROKE_POINTS_MS = 3000;
|
|
11
17
|
/**
|
|
12
18
|
* A small area to try brush settings before saving them: strokes are drawn in black, at the settings' own size, on a
|
|
13
19
|
* white background at double resolution (800 × 320 pixels shown in the window's width). "Clear" (a red pill) empties it.
|
|
20
|
+
* "Show stroke points" draws the stroke's sampled points (pink circles) and where it placed stamps (blue dots) over it,
|
|
21
|
+
* like the canvas's debug overlay, to see how sampling and smoothing work. They go 3 seconds after the stroke ends, or
|
|
22
|
+
* on "Clear".
|
|
14
23
|
*
|
|
15
24
|
* @example
|
|
16
25
|
* html`<pc-brush-test .config=${config} .tips=${app.tips}></pc-brush-test>`
|
|
@@ -23,6 +32,10 @@ export declare class PcBrushTest extends PcElement {
|
|
|
23
32
|
tips: {
|
|
24
33
|
attribute: boolean;
|
|
25
34
|
};
|
|
35
|
+
showPoints: {
|
|
36
|
+
type: BooleanConstructor;
|
|
37
|
+
attribute: string;
|
|
38
|
+
};
|
|
26
39
|
translations: {
|
|
27
40
|
attribute: boolean;
|
|
28
41
|
};
|
|
@@ -39,6 +52,9 @@ export declare class PcBrushTest extends PcElement {
|
|
|
39
52
|
config?: BrushConfig;
|
|
40
53
|
/** Brush shapes */
|
|
41
54
|
tips?: BrushTipCache;
|
|
55
|
+
/** Whether the last stroke's sampled points and stamps are drawn over it */
|
|
56
|
+
showPoints: boolean;
|
|
57
|
+
constructor();
|
|
42
58
|
/** Creates the layer and stroke canvases (replaceable for tests) */
|
|
43
59
|
createCanvas: CanvasFactory;
|
|
44
60
|
private layer?;
|
|
@@ -46,6 +62,8 @@ export declare class PcBrushTest extends PcElement {
|
|
|
46
62
|
/** The pointer drawing, if any */
|
|
47
63
|
private pointerId?;
|
|
48
64
|
private readonly onEngineChange;
|
|
65
|
+
/** Clears the finished stroke's points once they've been shown long enough */
|
|
66
|
+
private pointsTimer?;
|
|
49
67
|
disconnectedCallback(): void;
|
|
50
68
|
/** The visible canvas */
|
|
51
69
|
private get canvas();
|
|
@@ -61,11 +79,19 @@ export declare class PcBrushTest extends PcElement {
|
|
|
61
79
|
private onPointerMove;
|
|
62
80
|
/** Finish the test stroke */
|
|
63
81
|
private onPointerUp;
|
|
82
|
+
/** Stop showing the last stroke's points and stamps (still recording the next stroke's while shown) */
|
|
83
|
+
private clearPoints;
|
|
84
|
+
/**
|
|
85
|
+
* Show or hide the last stroke's sampled points and stamps. They're recorded from the next stroke.
|
|
86
|
+
*/
|
|
87
|
+
setShowPoints(shown: boolean): void;
|
|
64
88
|
/**
|
|
65
89
|
* Empty the testing area.
|
|
66
90
|
*/
|
|
67
91
|
clear(): void;
|
|
68
92
|
/** Show the layer (with any stroke in progress) on the visible canvas */
|
|
69
93
|
private paint;
|
|
94
|
+
/** Draw the last stroke's sampled points (circles) and stamp positions (dots) */
|
|
95
|
+
private paintPoints;
|
|
70
96
|
render(): import("lit").TemplateResult<1>;
|
|
71
97
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import style_default from "./style.js";
|
|
2
|
+
import { PILLS_CSS } from "../../styles/index.js";
|
|
2
3
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
3
4
|
import StrokeEngine from "../../../lib/brushes/StrokeEngine/index.js";
|
|
4
5
|
import Layer, { createOffscreenCanvas } from "../../../lib/classes/Layer/index.js";
|
|
@@ -10,9 +11,20 @@ var TEST_AREA_WIDTH = 800;
|
|
|
10
11
|
var TEST_AREA_HEIGHT = 320;
|
|
11
12
|
/** The colour test strokes are drawn in, whatever the current colour */
|
|
12
13
|
var TEST_COLOUR = "#000000";
|
|
14
|
+
/** The colour of the circles showing a stroke's sampled points, while stroke points are shown */
|
|
15
|
+
var POINT_COLOUR = "#e8175d";
|
|
16
|
+
/** The colour of the dots showing where a stroke placed its stamps, while stroke points are shown */
|
|
17
|
+
var STAMP_COLOUR = "#1e88e5";
|
|
18
|
+
/** How long a finished stroke's points stay shown (milliseconds) */
|
|
19
|
+
var STROKE_POINTS_MS = 3e3;
|
|
20
|
+
/** Radius of the circles showing a stroke's sampled points (test area pixels) */
|
|
21
|
+
var POINT_RADIUS = 8;
|
|
13
22
|
/**
|
|
14
23
|
* A small area to try brush settings before saving them: strokes are drawn in black, at the settings' own size, on a
|
|
15
24
|
* white background at double resolution (800 × 320 pixels shown in the window's width). "Clear" (a red pill) empties it.
|
|
25
|
+
* "Show stroke points" draws the stroke's sampled points (pink circles) and where it placed stamps (blue dots) over it,
|
|
26
|
+
* like the canvas's debug overlay, to see how sampling and smoothing work. They go 3 seconds after the stroke ends, or
|
|
27
|
+
* on "Clear".
|
|
16
28
|
*
|
|
17
29
|
* @example
|
|
18
30
|
* html`<pc-brush-test .config=${config} .tips=${app.tips}></pc-brush-test>`
|
|
@@ -21,9 +33,21 @@ var PcBrushTest = class extends PcElement {
|
|
|
21
33
|
static properties = {
|
|
22
34
|
...PcElement.properties,
|
|
23
35
|
config: { attribute: false },
|
|
24
|
-
tips: { attribute: false }
|
|
36
|
+
tips: { attribute: false },
|
|
37
|
+
showPoints: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
attribute: "show-points"
|
|
40
|
+
}
|
|
25
41
|
};
|
|
26
|
-
static styles = [
|
|
42
|
+
static styles = [
|
|
43
|
+
PcElement.styles,
|
|
44
|
+
unsafeCSS(PILLS_CSS),
|
|
45
|
+
unsafeCSS(style_default)
|
|
46
|
+
];
|
|
47
|
+
constructor() {
|
|
48
|
+
super();
|
|
49
|
+
this.showPoints = false;
|
|
50
|
+
}
|
|
27
51
|
/** Creates the layer and stroke canvases (replaceable for tests) */
|
|
28
52
|
createCanvas = createOffscreenCanvas;
|
|
29
53
|
layer;
|
|
@@ -31,8 +55,11 @@ var PcBrushTest = class extends PcElement {
|
|
|
31
55
|
/** The pointer drawing, if any */
|
|
32
56
|
pointerId;
|
|
33
57
|
onEngineChange = () => this.paint();
|
|
58
|
+
/** Clears the finished stroke's points once they've been shown long enough */
|
|
59
|
+
pointsTimer;
|
|
34
60
|
disconnectedCallback() {
|
|
35
61
|
super.disconnectedCallback();
|
|
62
|
+
clearTimeout(this.pointsTimer);
|
|
36
63
|
this.engine?.removeEventListener("change", this.onEngineChange);
|
|
37
64
|
}
|
|
38
65
|
/** The visible canvas */
|
|
@@ -45,6 +72,7 @@ var PcBrushTest = class extends PcElement {
|
|
|
45
72
|
if (!this.engine) {
|
|
46
73
|
this.engine = new StrokeEngine(800, 320, this.createCanvas);
|
|
47
74
|
this.engine.addEventListener("change", this.onEngineChange);
|
|
75
|
+
this.engine.setDebug(this.showPoints);
|
|
48
76
|
}
|
|
49
77
|
return {
|
|
50
78
|
layer: this.layer,
|
|
@@ -72,6 +100,7 @@ var PcBrushTest = class extends PcElement {
|
|
|
72
100
|
const config = this.config;
|
|
73
101
|
if (!config || !this.tips || event.button !== 0) return;
|
|
74
102
|
const { layer, engine } = this.drawing;
|
|
103
|
+
clearTimeout(this.pointsTimer);
|
|
75
104
|
this.pointerId = event.pointerId;
|
|
76
105
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
77
106
|
engine.begin({
|
|
@@ -98,12 +127,29 @@ var PcBrushTest = class extends PcElement {
|
|
|
98
127
|
this.pointerId = void 0;
|
|
99
128
|
this.engine?.end(this.point(event), event.timeStamp);
|
|
100
129
|
this.paint();
|
|
130
|
+
clearTimeout(this.pointsTimer);
|
|
131
|
+
this.pointsTimer = setTimeout(() => this.clearPoints(), STROKE_POINTS_MS);
|
|
132
|
+
}
|
|
133
|
+
/** Stop showing the last stroke's points and stamps (still recording the next stroke's while shown) */
|
|
134
|
+
clearPoints() {
|
|
135
|
+
clearTimeout(this.pointsTimer);
|
|
136
|
+
this.engine?.setDebug(this.showPoints);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Show or hide the last stroke's sampled points and stamps. They're recorded from the next stroke.
|
|
140
|
+
*/
|
|
141
|
+
setShowPoints(shown) {
|
|
142
|
+
const changed = shown !== this.showPoints;
|
|
143
|
+
this.showPoints = shown;
|
|
144
|
+
if (changed) this.engine?.setDebug(shown);
|
|
145
|
+
this.paint();
|
|
101
146
|
}
|
|
102
147
|
/**
|
|
103
148
|
* Empty the testing area.
|
|
104
149
|
*/
|
|
105
150
|
clear() {
|
|
106
151
|
this.engine?.cancel();
|
|
152
|
+
this.clearPoints();
|
|
107
153
|
this.layer?.context.clearRect(0, 0, 800, 320);
|
|
108
154
|
this.paint();
|
|
109
155
|
}
|
|
@@ -114,6 +160,23 @@ var PcBrushTest = class extends PcElement {
|
|
|
114
160
|
ctx.clearRect(0, 0, 800, 320);
|
|
115
161
|
const image = this.engine?.preview?.image ?? this.layer?.canvas;
|
|
116
162
|
if (image) ctx.drawImage(image, 0, 0);
|
|
163
|
+
if (this.showPoints && this.engine) this.paintPoints(ctx, this.engine);
|
|
164
|
+
}
|
|
165
|
+
/** Draw the last stroke's sampled points (circles) and stamp positions (dots) */
|
|
166
|
+
paintPoints(ctx, engine) {
|
|
167
|
+
const { points, stamps } = engine.debugTrace;
|
|
168
|
+
ctx.save();
|
|
169
|
+
ctx.fillStyle = STAMP_COLOUR;
|
|
170
|
+
for (const { x, y } of stamps) ctx.fillRect(x - 2, y - 2, 4, 4);
|
|
171
|
+
ctx.strokeStyle = POINT_COLOUR;
|
|
172
|
+
ctx.lineWidth = 2;
|
|
173
|
+
ctx.beginPath();
|
|
174
|
+
for (const { x, y } of points) {
|
|
175
|
+
ctx.moveTo(x + POINT_RADIUS, y);
|
|
176
|
+
ctx.arc(x, y, POINT_RADIUS, 0, Math.PI * 2);
|
|
177
|
+
}
|
|
178
|
+
ctx.stroke();
|
|
179
|
+
ctx.restore();
|
|
117
180
|
}
|
|
118
181
|
render() {
|
|
119
182
|
return html`
|
|
@@ -126,11 +189,21 @@ var PcBrushTest = class extends PcElement {
|
|
|
126
189
|
@pointerup=${this.onPointerUp}
|
|
127
190
|
@pointercancel=${this.onPointerUp}
|
|
128
191
|
></canvas>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
192
|
+
<div class="actions">
|
|
193
|
+
<button type="button" class="pill clear" @click=${() => this.clear()}>
|
|
194
|
+
${this.t("paintCanvas.common.clear")}
|
|
195
|
+
</button>
|
|
196
|
+
<label class="show-points">
|
|
197
|
+
<input
|
|
198
|
+
type="checkbox"
|
|
199
|
+
.checked=${this.showPoints}
|
|
200
|
+
@change=${(e) => this.setShowPoints(e.target.checked)}
|
|
201
|
+
/>
|
|
202
|
+
${this.t("paintCanvas.brushConfig.showStrokePoints")}
|
|
203
|
+
</label>
|
|
204
|
+
</div>
|
|
132
205
|
`;
|
|
133
206
|
}
|
|
134
207
|
};
|
|
135
208
|
defineElement("pc-brush-test", PcBrushTest);
|
|
136
|
-
export { PcBrushTest, TEST_AREA_HEIGHT, TEST_AREA_WIDTH, TEST_COLOUR };
|
|
209
|
+
export { POINT_COLOUR, PcBrushTest, STAMP_COLOUR, STROKE_POINTS_MS, TEST_AREA_HEIGHT, TEST_AREA_WIDTH, TEST_COLOUR };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcBrushTest/style.css?inline
|
|
2
|
-
var style_default = ":host {\n display: block;\n}\ncanvas {\n display: block;\n width: 100%;\n background: #fff;\n border: 1px solid var(--pc-border);\n touch-action: none;\n}\n/* \"Clear\"
|
|
2
|
+
var style_default = ":host {\n display: block;\n}\ncanvas {\n display: block;\n width: 100%;\n background: #fff;\n border: 1px solid var(--pc-border);\n touch-action: none;\n}\n/* \"Clear\", then \"Show stroke points\" */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin-top: 6px;\n}\n.show-points {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n cursor: pointer;\n}\n/* \"Clear\": a red pill */\nbutton.pill.clear {\n background: var(--pc-red);\n color: #ffffff;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { PcElement } from "../../base";
|
|
2
|
+
import { type PillSize } from "../../styles";
|
|
2
3
|
import "../PcIcon";
|
|
3
4
|
/** How a button looks */
|
|
4
5
|
export type ButtonVariant = "accent" | "cancel" | "dismiss" | "pill" | "icon";
|
|
5
6
|
/**
|
|
6
|
-
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a pill (`pill`,
|
|
8
|
+
* the same as `accent`), or a boxed icon button (`icon`, which needs a `label` for screen readers). Its text goes in its
|
|
9
|
+
* content. All but icon buttons are pills, of the `size` given (`pill` by default; see `PILL_SIZE_STYLES`). Clicks
|
|
10
|
+
* reach listeners on the element; a disabled button sends none.
|
|
9
11
|
*
|
|
10
12
|
* @example
|
|
11
13
|
* html`<pc-button variant="cancel" @click=${close}>Cancel</pc-button>`
|
|
14
|
+
* html`<pc-button size="pill-l">Start</pc-button>`
|
|
12
15
|
* html`<pc-button variant="icon" icon="undo" label="Undo"></pc-button>`
|
|
13
16
|
*/
|
|
14
17
|
export declare class PcButton extends PcElement {
|
|
@@ -17,6 +20,10 @@ export declare class PcButton extends PcElement {
|
|
|
17
20
|
type: StringConstructor;
|
|
18
21
|
reflect: boolean;
|
|
19
22
|
};
|
|
23
|
+
size: {
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
reflect: boolean;
|
|
26
|
+
};
|
|
20
27
|
icon: {
|
|
21
28
|
type: StringConstructor;
|
|
22
29
|
};
|
|
@@ -43,6 +50,8 @@ export declare class PcButton extends PcElement {
|
|
|
43
50
|
};
|
|
44
51
|
static styles: import("lit").CSSResultGroup[];
|
|
45
52
|
variant: ButtonVariant;
|
|
53
|
+
/** How big the pill is (not for icon buttons) */
|
|
54
|
+
size: PillSize;
|
|
46
55
|
/** Name of an icon to show before the text (or alone, for an icon button) */
|
|
47
56
|
icon?: string;
|
|
48
57
|
/** The button's name for screen readers, when its content doesn't say it (e.g. an icon button) */
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
2
|
+
import { PILL_SIZES, pillSizeDeclarations } from "../../styles/index.js";
|
|
2
3
|
import "../PcIcon/index.js";
|
|
3
|
-
import { css, html, nothing } from "lit";
|
|
4
|
+
import { css, html, nothing, unsafeCSS } from "lit";
|
|
4
5
|
// src/ui/elements/PcButton/index.ts
|
|
6
|
+
/** Each pill size, for the buttons that are pills (all but icon buttons) */
|
|
7
|
+
var SIZE_STYLES = unsafeCSS(PILL_SIZES.map((size) => `:host([size="${size}"]) button { ${pillSizeDeclarations(size)} }`).join("\n"));
|
|
5
8
|
/**
|
|
6
|
-
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
+
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a pill (`pill`,
|
|
10
|
+
* the same as `accent`), or a boxed icon button (`icon`, which needs a `label` for screen readers). Its text goes in its
|
|
11
|
+
* content. All but icon buttons are pills, of the `size` given (`pill` by default; see `PILL_SIZE_STYLES`). Clicks
|
|
12
|
+
* reach listeners on the element; a disabled button sends none.
|
|
9
13
|
*
|
|
10
14
|
* @example
|
|
11
15
|
* html`<pc-button variant="cancel" @click=${close}>Cancel</pc-button>`
|
|
16
|
+
* html`<pc-button size="pill-l">Start</pc-button>`
|
|
12
17
|
* html`<pc-button variant="icon" icon="undo" label="Undo"></pc-button>`
|
|
13
18
|
*/
|
|
14
19
|
var PcButton = class extends PcElement {
|
|
@@ -18,6 +23,10 @@ var PcButton = class extends PcElement {
|
|
|
18
23
|
type: String,
|
|
19
24
|
reflect: true
|
|
20
25
|
},
|
|
26
|
+
size: {
|
|
27
|
+
type: String,
|
|
28
|
+
reflect: true
|
|
29
|
+
},
|
|
21
30
|
icon: { type: String },
|
|
22
31
|
label: { type: String },
|
|
23
32
|
disabled: {
|
|
@@ -38,9 +47,8 @@ var PcButton = class extends PcElement {
|
|
|
38
47
|
flex: 1;
|
|
39
48
|
align-items: center;
|
|
40
49
|
justify-content: center;
|
|
50
|
+
box-sizing: border-box;
|
|
41
51
|
gap: var(--pc-space-1);
|
|
42
|
-
min-height: var(--pc-control-size);
|
|
43
|
-
padding: var(--pc-space-1) var(--pc-space-3);
|
|
44
52
|
border: 0;
|
|
45
53
|
/* A joined button group gives each button its corners */
|
|
46
54
|
border-radius: var(--pc-group-radius, var(--pc-radius-pill));
|
|
@@ -48,10 +56,11 @@ var PcButton = class extends PcElement {
|
|
|
48
56
|
color: var(--pc-accent-text);
|
|
49
57
|
font: inherit;
|
|
50
58
|
font-family: var(--pc-font);
|
|
51
|
-
|
|
59
|
+
${unsafeCSS(pillSizeDeclarations("pill"))}
|
|
52
60
|
font-weight: bold;
|
|
53
61
|
cursor: pointer;
|
|
54
62
|
}
|
|
63
|
+
${SIZE_STYLES}
|
|
55
64
|
button:hover:not(:disabled) {
|
|
56
65
|
filter: brightness(1.15);
|
|
57
66
|
}
|
|
@@ -76,12 +85,10 @@ var PcButton = class extends PcElement {
|
|
|
76
85
|
filter: none;
|
|
77
86
|
text-decoration: underline;
|
|
78
87
|
}
|
|
79
|
-
:host([variant="pill"]) button {
|
|
80
|
-
min-height: 30px;
|
|
81
|
-
}
|
|
82
88
|
:host([variant="icon"]) button {
|
|
83
89
|
min-height: 0;
|
|
84
90
|
padding: 2px;
|
|
91
|
+
line-height: normal;
|
|
85
92
|
border: 1px solid var(--pc-border);
|
|
86
93
|
border-radius: var(--pc-group-radius, var(--pc-radius-small));
|
|
87
94
|
background: var(--pc-surface);
|
|
@@ -101,6 +108,7 @@ var PcButton = class extends PcElement {
|
|
|
101
108
|
constructor() {
|
|
102
109
|
super();
|
|
103
110
|
this.variant = "accent";
|
|
111
|
+
this.size = "pill";
|
|
104
112
|
this.disabled = false;
|
|
105
113
|
}
|
|
106
114
|
/** Move keyboard focus to the button */
|
|
@@ -15,6 +15,8 @@ export declare const HANDLE_GRAB_DISTANCE = 8;
|
|
|
15
15
|
export declare const ANTS_INTERVAL = 100;
|
|
16
16
|
/** In focus pen mode, how long after a pen lifts touches are still ignored (milliseconds) */
|
|
17
17
|
export declare const PEN_LIFT_GRACE_MS = 500;
|
|
18
|
+
/** The most device pixels per CSS pixel the canvases on screen use (see `PcCanvas.pixelRatio`) */
|
|
19
|
+
export declare const MAX_PIXEL_RATIO = 2;
|
|
18
20
|
/**
|
|
19
21
|
* Space covered by the toolbar and chat on a screen of the given width.
|
|
20
22
|
*
|
|
@@ -92,7 +94,10 @@ export declare class PcCanvas extends PcElement {
|
|
|
92
94
|
insets?: Insets;
|
|
93
95
|
/** The insets in effect (see `insets`) */
|
|
94
96
|
private get activeInsets();
|
|
95
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Device pixels per CSS pixel for the canvases on screen, at most `MAX_PIXEL_RATIO`: phones with 3 have 2.25 times
|
|
99
|
+
* the pixels to draw and put on screen for little visible difference (replaceable for tests).
|
|
100
|
+
*/
|
|
96
101
|
pixelRatio: () => number;
|
|
97
102
|
private changes;
|
|
98
103
|
/** Whether anything but the stroke in progress changed since the last update (so everything is redrawn) */
|
|
@@ -123,6 +128,8 @@ export declare class PcCanvas extends PcElement {
|
|
|
123
128
|
private drag;
|
|
124
129
|
/** Pointer drawing the current stroke, and the layer it draws on */
|
|
125
130
|
private stroke;
|
|
131
|
+
/** A press that closed a panel or menu, held until it moves far enough to count (see `onPointerDown`) */
|
|
132
|
+
private heldPress;
|
|
126
133
|
/** Pointer position over the stage (for the brush cursor), or null when outside */
|
|
127
134
|
private hover;
|
|
128
135
|
/** Name of the key held to zoom with the scroll wheel (replaceable for tests) */
|
|
@@ -256,15 +263,33 @@ export declare class PcCanvas extends PcElement {
|
|
|
256
263
|
* Get a pointer's position relative to the stage.
|
|
257
264
|
*/
|
|
258
265
|
private pointerPoint;
|
|
266
|
+
/**
|
|
267
|
+
* Send a pointer's events to the canvas until it's lifted, even outside it.
|
|
268
|
+
*/
|
|
269
|
+
private capturePointer;
|
|
270
|
+
/**
|
|
271
|
+
* Handle a press, unless it closed a panel or menu (see `isDismissingPress`): that press is held, and only starts
|
|
272
|
+
* drawing (or whatever the tool does) once it moves `DRAG_THRESHOLD` pixels, so tapping the canvas to close a panel
|
|
273
|
+
* leaves no mark.
|
|
274
|
+
*/
|
|
275
|
+
private onPointerDown;
|
|
276
|
+
/**
|
|
277
|
+
* Start a held press (see `onPointerDown`) once it moves far enough. Returns whether the pointer is still held.
|
|
278
|
+
*/
|
|
279
|
+
private releaseHeldPress;
|
|
259
280
|
/**
|
|
260
281
|
* Start panning, or zoom, depending on the tool and button. In focus pen mode, touches only pan, pinch and make
|
|
261
282
|
* gestures, and are ignored while a pen is down or just lifted (see `focusPenTouch`).
|
|
262
283
|
*/
|
|
263
|
-
private
|
|
284
|
+
private pointerDown;
|
|
264
285
|
/**
|
|
265
286
|
* Continue a stroke (using every in-between event the browser recorded), pan while dragging, and move the brush cursor.
|
|
266
287
|
*/
|
|
267
288
|
private onPointerMove;
|
|
289
|
+
/**
|
|
290
|
+
* Forget a held press lifted (or cancelled) before it moved far enough. Returns whether it was one.
|
|
291
|
+
*/
|
|
292
|
+
private dropHeldPress;
|
|
268
293
|
/**
|
|
269
294
|
* Finish a stroke (writing it into the layer) or stop panning.
|
|
270
295
|
*/
|
|
@@ -4,6 +4,8 @@ import style_default from "./style.js";
|
|
|
4
4
|
import { NO_TEXT_SELECTION_CSS } from "../../styles/index.js";
|
|
5
5
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
6
6
|
import ChangeController from "../../ChangeController/index.js";
|
|
7
|
+
import { isDismissingPress } from "../../dismiss/index.js";
|
|
8
|
+
import "../../drag/index.js";
|
|
7
9
|
import "../../../lib/classes/PaintCanvas/index.js";
|
|
8
10
|
import { PASTEBOARD_COLOUR, drawScene } from "../../../lib/rendering/compositing/index.js";
|
|
9
11
|
import { drawBrushCursor } from "../../../lib/rendering/cursor/index.js";
|
|
@@ -37,6 +39,8 @@ var HANDLE_GRAB_DISTANCE = 8;
|
|
|
37
39
|
var ANTS_INTERVAL = 100;
|
|
38
40
|
/** In focus pen mode, how long after a pen lifts touches are still ignored (milliseconds) */
|
|
39
41
|
var PEN_LIFT_GRACE_MS = 500;
|
|
42
|
+
/** The most device pixels per CSS pixel the canvases on screen use (see `PcCanvas.pixelRatio`) */
|
|
43
|
+
var MAX_PIXEL_RATIO = 2;
|
|
40
44
|
/**
|
|
41
45
|
* Space covered by the toolbar and chat on a screen of the given width.
|
|
42
46
|
*
|
|
@@ -129,8 +133,11 @@ var PcCanvas = class extends PcElement {
|
|
|
129
133
|
const app = this.app;
|
|
130
134
|
return this.insets ?? interfaceInsets(app.viewport.width, app.interfaceVisible);
|
|
131
135
|
}
|
|
132
|
-
/**
|
|
133
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Device pixels per CSS pixel for the canvases on screen, at most `MAX_PIXEL_RATIO`: phones with 3 have 2.25 times
|
|
138
|
+
* the pixels to draw and put on screen for little visible difference (replaceable for tests).
|
|
139
|
+
*/
|
|
140
|
+
pixelRatio = () => Math.min(window.devicePixelRatio || 1, 2);
|
|
134
141
|
changes = new ChangeController(this, () => [
|
|
135
142
|
this.app,
|
|
136
143
|
this.app?.brush,
|
|
@@ -172,6 +179,8 @@ var PcCanvas = class extends PcElement {
|
|
|
172
179
|
drag = null;
|
|
173
180
|
/** Pointer drawing the current stroke, and the layer it draws on */
|
|
174
181
|
stroke = null;
|
|
182
|
+
/** A press that closed a panel or menu, held until it moves far enough to count (see `onPointerDown`) */
|
|
183
|
+
heldPress = null;
|
|
175
184
|
/** Pointer position over the stage (for the brush cursor), or null when outside */
|
|
176
185
|
hover = null;
|
|
177
186
|
/** Name of the key held to zoom with the scroll wheel (replaceable for tests) */
|
|
@@ -238,6 +247,7 @@ var PcCanvas = class extends PcElement {
|
|
|
238
247
|
this.frame = 0;
|
|
239
248
|
}
|
|
240
249
|
firstUpdated() {
|
|
250
|
+
this.canvas?.getContext("2d", { willReadFrequently: true });
|
|
241
251
|
if (typeof ResizeObserver !== "undefined") {
|
|
242
252
|
this.resizeObserver = new ResizeObserver(() => this.syncSize());
|
|
243
253
|
this.resizeObserver.observe(this);
|
|
@@ -425,7 +435,7 @@ var PcCanvas = class extends PcElement {
|
|
|
425
435
|
point: app.viewport.screenToCanvas(screen),
|
|
426
436
|
constrain: app.constrainProportions
|
|
427
437
|
};
|
|
428
|
-
|
|
438
|
+
this.capturePointer(event.pointerId);
|
|
429
439
|
}
|
|
430
440
|
/**
|
|
431
441
|
* Update the transform box while dragging.
|
|
@@ -499,7 +509,7 @@ var PcCanvas = class extends PcElement {
|
|
|
499
509
|
const point = this.pointerPoint(event);
|
|
500
510
|
const first = app.lasso.nodes[0];
|
|
501
511
|
const nearFirstNode = first !== void 0 && isNear(app.viewport.canvasToScreen(first), point, 8);
|
|
502
|
-
if (kind !== "polygon")
|
|
512
|
+
if (kind !== "polygon") this.capturePointer(event.pointerId);
|
|
503
513
|
app.applyLasso(app.lasso.down(kind, app.viewport.screenToCanvas(point), event, nearFirstNode));
|
|
504
514
|
}
|
|
505
515
|
/**
|
|
@@ -563,7 +573,7 @@ var PcCanvas = class extends PcElement {
|
|
|
563
573
|
pointerId: event.pointerId,
|
|
564
574
|
layerId: layer.id
|
|
565
575
|
};
|
|
566
|
-
|
|
576
|
+
this.capturePointer(event.pointerId);
|
|
567
577
|
const erasing = app.activeTool === Tool.Eraser;
|
|
568
578
|
app.strokes.begin({
|
|
569
579
|
layer,
|
|
@@ -594,12 +604,42 @@ var PcCanvas = class extends PcElement {
|
|
|
594
604
|
};
|
|
595
605
|
}
|
|
596
606
|
/**
|
|
607
|
+
* Send a pointer's events to the canvas until it's lifted, even outside it.
|
|
608
|
+
*/
|
|
609
|
+
capturePointer(pointerId) {
|
|
610
|
+
this.renderRoot.querySelector("canvas.scene")?.setPointerCapture?.(pointerId);
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Handle a press, unless it closed a panel or menu (see `isDismissingPress`): that press is held, and only starts
|
|
614
|
+
* drawing (or whatever the tool does) once it moves `DRAG_THRESHOLD` pixels, so tapping the canvas to close a panel
|
|
615
|
+
* leaves no mark.
|
|
616
|
+
*/
|
|
617
|
+
onPointerDown(event) {
|
|
618
|
+
if (!this.app) return;
|
|
619
|
+
if (!isDismissingPress(event)) {
|
|
620
|
+
this.pointerDown(event);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
this.heldPress = event;
|
|
624
|
+
this.capturePointer(event.pointerId);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Start a held press (see `onPointerDown`) once it moves far enough. Returns whether the pointer is still held.
|
|
628
|
+
*/
|
|
629
|
+
releaseHeldPress(event) {
|
|
630
|
+
const held = this.heldPress;
|
|
631
|
+
if (held?.pointerId !== event.pointerId) return false;
|
|
632
|
+
if (Math.hypot(event.clientX - held.clientX, event.clientY - held.clientY) < 4) return true;
|
|
633
|
+
this.heldPress = null;
|
|
634
|
+
this.pointerDown(held);
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
597
638
|
* Start panning, or zoom, depending on the tool and button. In focus pen mode, touches only pan, pinch and make
|
|
598
639
|
* gestures, and are ignored while a pen is down or just lifted (see `focusPenTouch`).
|
|
599
640
|
*/
|
|
600
|
-
|
|
641
|
+
pointerDown(event) {
|
|
601
642
|
const app = this.app;
|
|
602
|
-
if (!app) return;
|
|
603
643
|
if (event.pointerType === "pen") this.penDown(event);
|
|
604
644
|
if (event.pointerType === "touch") {
|
|
605
645
|
const ignored = this.focusPenTouch(event);
|
|
@@ -632,7 +672,7 @@ var PcCanvas = class extends PcElement {
|
|
|
632
672
|
pointerId: event.pointerId,
|
|
633
673
|
last: point
|
|
634
674
|
};
|
|
635
|
-
|
|
675
|
+
this.capturePointer(event.pointerId);
|
|
636
676
|
this.updateCursor();
|
|
637
677
|
} else if (app.activeTool === Tool.Zoom && event.button === 0) {
|
|
638
678
|
if (event.altKey) app.viewport.zoomOut(point);
|
|
@@ -645,6 +685,7 @@ var PcCanvas = class extends PcElement {
|
|
|
645
685
|
onPointerMove(event) {
|
|
646
686
|
const app = this.app;
|
|
647
687
|
if (!app || this.ignoredTouches.has(event.pointerId)) return;
|
|
688
|
+
if (this.releaseHeldPress(event)) return;
|
|
648
689
|
const point = this.pointerPoint(event);
|
|
649
690
|
if (this.touches.has(event.pointerId)) {
|
|
650
691
|
this.touches.set(event.pointerId, point);
|
|
@@ -680,10 +721,18 @@ var PcCanvas = class extends PcElement {
|
|
|
680
721
|
this.requestOverlay();
|
|
681
722
|
}
|
|
682
723
|
/**
|
|
724
|
+
* Forget a held press lifted (or cancelled) before it moved far enough. Returns whether it was one.
|
|
725
|
+
*/
|
|
726
|
+
dropHeldPress(event) {
|
|
727
|
+
if (this.heldPress?.pointerId !== event.pointerId) return false;
|
|
728
|
+
this.heldPress = null;
|
|
729
|
+
return true;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
683
732
|
* Finish a stroke (writing it into the layer) or stop panning.
|
|
684
733
|
*/
|
|
685
734
|
onPointerUp(event) {
|
|
686
|
-
if (this.ignoredTouches.delete(event.pointerId)) return;
|
|
735
|
+
if (this.ignoredTouches.delete(event.pointerId) || this.dropHeldPress(event)) return;
|
|
687
736
|
this.penUp(event);
|
|
688
737
|
this.touchUp(event);
|
|
689
738
|
if (this.sampling?.pointerId === event.pointerId) this.finishSample();
|
|
@@ -713,7 +762,7 @@ var PcCanvas = class extends PcElement {
|
|
|
713
762
|
* Abandon a stroke or pan when the browser cancels the pointer (e.g. a system gesture).
|
|
714
763
|
*/
|
|
715
764
|
onPointerCancel(event) {
|
|
716
|
-
if (this.ignoredTouches.delete(event.pointerId)) return;
|
|
765
|
+
if (this.ignoredTouches.delete(event.pointerId) || this.dropHeldPress(event)) return;
|
|
717
766
|
this.navigationTouches.delete(event.pointerId);
|
|
718
767
|
this.penUp(event);
|
|
719
768
|
this.touchUp(event);
|
|
@@ -791,7 +840,7 @@ var PcCanvas = class extends PcElement {
|
|
|
791
840
|
this.drag = null;
|
|
792
841
|
const [a, b] = [...this.touches.values()];
|
|
793
842
|
this.pinch = touchPair(a, b);
|
|
794
|
-
|
|
843
|
+
this.capturePointer(event.pointerId);
|
|
795
844
|
}
|
|
796
845
|
return true;
|
|
797
846
|
}
|
|
@@ -809,7 +858,7 @@ var PcCanvas = class extends PcElement {
|
|
|
809
858
|
point,
|
|
810
859
|
screen
|
|
811
860
|
};
|
|
812
|
-
|
|
861
|
+
this.capturePointer(event.pointerId);
|
|
813
862
|
this.updateCursor();
|
|
814
863
|
this.drawOverlay();
|
|
815
864
|
}
|
|
@@ -841,6 +890,7 @@ var PcCanvas = class extends PcElement {
|
|
|
841
890
|
if (!ctx) return;
|
|
842
891
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
843
892
|
const sampling = this.sampling;
|
|
893
|
+
this.sampler.hidden = !sampling;
|
|
844
894
|
if (!sampling) return;
|
|
845
895
|
const ratio = this.pixelRatio();
|
|
846
896
|
ctx.save();
|
|
@@ -1003,4 +1053,4 @@ var PcCanvas = class extends PcElement {
|
|
|
1003
1053
|
}
|
|
1004
1054
|
};
|
|
1005
1055
|
defineElement("pc-canvas", PcCanvas);
|
|
1006
|
-
export { ANTS_INTERVAL, CHAT_WIDTH_RATIO, HANDLE_GRAB_DISTANCE, LASSO_TOOLS, PEN_LIFT_GRACE_MS, PcCanvas, SAMPLER_HEIGHT, SAMPLER_WIDTH, TOOLBAR_WIDTH, TOUCH_SAMPLER_GAP, cursorFor, interfaceInsets, samplerPosition };
|
|
1056
|
+
export { ANTS_INTERVAL, CHAT_WIDTH_RATIO, HANDLE_GRAB_DISTANCE, LASSO_TOOLS, MAX_PIXEL_RATIO, PEN_LIFT_GRACE_MS, PcCanvas, SAMPLER_HEIGHT, SAMPLER_WIDTH, TOOLBAR_WIDTH, TOUCH_SAMPLER_GAP, cursorFor, interfaceInsets, samplerPosition };
|