@edv4h/usketch-plugin-shape-freedraw 3.3.3 → 3.4.1

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.
Files changed (49) hide show
  1. package/README.md +34 -1
  2. package/dist/config.d.ts +2 -7
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +7 -4
  5. package/dist/config.js.map +1 -1
  6. package/dist/custom-pens.d.ts +68 -0
  7. package/dist/custom-pens.d.ts.map +1 -0
  8. package/dist/custom-pens.js +72 -0
  9. package/dist/custom-pens.js.map +1 -0
  10. package/dist/draw-tool.d.ts +1 -1
  11. package/dist/draw-tool.d.ts.map +1 -1
  12. package/dist/draw-tool.js +14 -8
  13. package/dist/draw-tool.js.map +1 -1
  14. package/dist/freedraw-service.d.ts +28 -0
  15. package/dist/freedraw-service.d.ts.map +1 -0
  16. package/dist/freedraw-service.js +32 -0
  17. package/dist/freedraw-service.js.map +1 -0
  18. package/dist/geometry/hit.d.ts +6 -1
  19. package/dist/geometry/hit.d.ts.map +1 -1
  20. package/dist/geometry/hit.js +81 -15
  21. package/dist/geometry/hit.js.map +1 -1
  22. package/dist/index.d.ts +5 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/pen-meta.d.ts +10 -3
  27. package/dist/pen-meta.d.ts.map +1 -1
  28. package/dist/pen-meta.js +26 -2
  29. package/dist/pen-meta.js.map +1 -1
  30. package/dist/plugin.d.ts +10 -1
  31. package/dist/plugin.d.ts.map +1 -1
  32. package/dist/plugin.js +27 -6
  33. package/dist/plugin.js.map +1 -1
  34. package/dist/settings-store.d.ts +6 -3
  35. package/dist/settings-store.d.ts.map +1 -1
  36. package/dist/settings-store.js +15 -2
  37. package/dist/settings-store.js.map +1 -1
  38. package/dist/shape.d.ts.map +1 -1
  39. package/dist/shape.js +9 -0
  40. package/dist/shape.js.map +1 -1
  41. package/dist/types.d.ts +10 -1
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/ui/cursor-overlay.d.ts +1 -1
  44. package/dist/ui/cursor-overlay.d.ts.map +1 -1
  45. package/dist/ui/cursor-overlay.js +7 -3
  46. package/dist/ui/cursor-overlay.js.map +1 -1
  47. package/dist/ui/palette.js +2 -2
  48. package/dist/ui/palette.js.map +1 -1
  49. package/package.json +5 -5
package/README.md CHANGED
@@ -34,6 +34,36 @@ const plugins = [
34
34
  一定幅ペンは中点を通る二次ベジェで平滑化、筆ペンは perfect-freehand で塗りアウトラインを生成。
35
35
  蛍光ペンは要素単位合成のため、同一ストローク内の交差は二重に濃くならず別ストローク同士は濃くなる。
36
36
 
37
+ ## 外からペンを足す
38
+
39
+ 組み込みの 4 種に、別のプラグインやホストがペンを足せる。足したペンのストロークも `freedraw`
40
+ shape なので、選択・移動・拡大縮小(点列だけを伸ばし、太さは変えない)・消しゴム・当たり判定・
41
+ undo・同期はそのまま効く。描画は SVG で、GPU には回さない。
42
+
43
+ ```tsx
44
+ createFreedrawPlugin(undefined, {
45
+ pens: [
46
+ {
47
+ id: "road", // shape の pen に入る。組み込みの id とは重ねない
48
+ label: "道路",
49
+ defaultSize: 120,
50
+ sizeRange: { min: 40, max: 400 }, // freedraw:set-size をこの範囲に丸める
51
+ usesColor: false, // ペン先カーソルを色なしで出す
52
+ render: (shape) => <Road shape={shape} />,
53
+ renderDraft: (shape) => <path d={...} />, // 描いている最中(shape.draft === true)
54
+ finalize: (points, { size }) => ({ points: tidy(points), penData: { closed: true } }),
55
+ halfWidth: (size) => size / 2 + 12, // 外接矩形・当たり判定・消しゴムの半幅
56
+ },
57
+ ],
58
+ });
59
+ ```
60
+
61
+ ペンは shape の描画と当たり判定に効くので、実行中に足し外しせず、プラグインの引数で渡す。
62
+ `getFreedrawApi(app.services)?.listPens()`(または `listPens()`)は組み込み → 足したペンの順で
63
+ 一覧を返すので、ペン選択 UI はこれで作れる。`finalize` が返す `penData` は移動・拡大縮小でそのまま
64
+ 写されるので、座標は入れない(点列から毎回作る)。
65
+ ペンを登録していないクライアントでは、そのストロークはボールペンの線(色・太さはそのまま)で描かれる。
66
+
37
67
  ## 消しゴム
38
68
 
39
69
  `mode: "eraser"` のとき、触れた freedraw ストロークを丸ごと削除する(ピクセル消去ではない)。
@@ -43,10 +73,13 @@ const plugins = [
43
73
 
44
74
  ```ts
45
75
  type PenKind = "ballpoint" | "felt" | "brush" | "highlighter";
76
+ type PenId = PenKind | string; // 外から足したペンの id も入る
46
77
  interface StrokePoint { x: number; y: number; p?: number } // p=疑似筆圧 0..1
47
78
  interface FreedrawShapeData extends ShapeData {
48
79
  points: StrokePoint[];
49
- pen?: PenKind; // 省略時 ballpoint(旧データ後方互換)
80
+ pen?: PenId; // 省略時 ballpoint(旧データ後方互換)
81
+ penData?: Record<string, unknown>; // 足したペンの finalize が返したデータ
82
+ draft?: boolean; // 描いている最中だけ true
50
83
  }
51
84
  ```
52
85
 
package/dist/config.d.ts CHANGED
@@ -28,19 +28,14 @@ export declare const TUNING: {
28
28
  };
29
29
  /** プラグイン設定(JSON 可、Zod 検証)。実行時の可変状態は settings-store が持つ。 */
30
30
  export declare const FreedrawConfigSchema: z.ZodObject<{
31
- defaultPen: z.ZodDefault<z.ZodEnum<{
32
- ballpoint: "ballpoint";
33
- brush: "brush";
34
- felt: "felt";
35
- highlighter: "highlighter";
36
- }>>;
31
+ defaultPen: z.ZodDefault<z.ZodString>;
37
32
  defaultColor: z.ZodDefault<z.ZodString>;
38
33
  defaultSizes: z.ZodDefault<z.ZodObject<{
39
34
  ballpoint: z.ZodNumber;
40
35
  felt: z.ZodNumber;
41
36
  brush: z.ZodNumber;
42
37
  highlighter: z.ZodNumber;
43
- }, z.core.$strip>>;
38
+ }, z.core.$catchall<z.ZodNumber>>>;
44
39
  defaultEraserSize: z.ZodDefault<z.ZodNumber>;
45
40
  brushDynamics: z.ZodDefault<z.ZodNumber>;
46
41
  hitTest: z.ZodDefault<z.ZodEnum<{
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,uCAAuC;AACvC,eAAO,MAAM,UAAU;aAAK,GAAG,EAAE,CAAC;aAAE,GAAG,EAAE,EAAE;aAAE,IAAI,EAAE,GAAG;CAAW,CAAC;AAClE,eAAO,MAAM,YAAY;aAAK,GAAG,EAAE,EAAE;aAAE,GAAG,EAAE,GAAG;aAAE,IAAI,EAAE,CAAC;CAAW,CAAC;AACpE,eAAO,MAAM,oBAAoB;aAAK,GAAG,EAAE,EAAE;aAAE,GAAG,EAAE,GAAG;aAAE,IAAI,EAAE,CAAC;CAAW,CAAC;AAE5E,qBAAqB;AACrB,eAAO,MAAM,MAAM;IAClB,yCAAyC;aACzC,aAAa,EAAE,GAAG;IAClB,+BAA+B;aAC/B,cAAc,EAAE,GAAG;IACnB,wBAAwB;aACxB,aAAa,EAAE,IAAI;IACnB,wCAAwC;aACxC,iBAAiB,EAAE,GAAG;CACb,CAAC;AASX,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;iBAoB/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAE/E;AAED,uBAAuB;AACvB,eAAO,MAAM,WAAW,+BAA+B,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,uCAAuC;AACvC,eAAO,MAAM,UAAU;aAAK,GAAG,EAAE,CAAC;aAAE,GAAG,EAAE,EAAE;aAAE,IAAI,EAAE,GAAG;CAAW,CAAC;AAClE,eAAO,MAAM,YAAY;aAAK,GAAG,EAAE,EAAE;aAAE,GAAG,EAAE,GAAG;aAAE,IAAI,EAAE,CAAC;CAAW,CAAC;AACpE,eAAO,MAAM,oBAAoB;aAAK,GAAG,EAAE,EAAE;aAAE,GAAG,EAAE,GAAG;aAAE,IAAI,EAAE,CAAC;CAAW,CAAC;AAE5E,qBAAqB;AACrB,eAAO,MAAM,MAAM;IAClB,yCAAyC;aACzC,aAAa,EAAE,GAAG;IAClB,+BAA+B;aAC/B,cAAc,EAAE,GAAG;IACnB,wBAAwB;aACxB,aAAa,EAAE,IAAI;IACnB,wCAAwC;aACxC,iBAAiB,EAAE,GAAG;CACb,CAAC;AAYX,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;iBAoB/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAE/E;AAED,uBAAuB;AACvB,eAAO,MAAM,WAAW,+BAA+B,CAAC"}
package/dist/config.js CHANGED
@@ -15,16 +15,19 @@ export const TUNING = {
15
15
  /** 確定時の RDP 間引き許容誤差(world px、0 で無効)。 */
16
16
  simplifyTolerance: 0.6,
17
17
  };
18
- const SizesSchema = z.object({
18
+ // 組み込みの 4 種は必須。外から足したペンの太さも id をキーにして持てる。
19
+ const SizesSchema = z
20
+ .object({
19
21
  ballpoint: z.number().positive(),
20
22
  felt: z.number().positive(),
21
23
  brush: z.number().positive(),
22
24
  highlighter: z.number().positive(),
23
- });
25
+ })
26
+ .catchall(z.number().positive());
24
27
  /** プラグイン設定(JSON 可、Zod 検証)。実行時の可変状態は settings-store が持つ。 */
25
28
  export const FreedrawConfigSchema = z.object({
26
- /** 既定ペン。 */
27
- defaultPen: z.enum(["ballpoint", "felt", "brush", "highlighter"]).default(DEFAULT_PEN),
29
+ /** 既定ペン(組み込みのペンか、外から足したペンの id)。 */
30
+ defaultPen: z.string().default(DEFAULT_PEN),
28
31
  /** 既定色。 */
29
32
  defaultColor: z.string().default(PRESET_COLORS[0]),
30
33
  /** ペンごとの既定太さ。 */
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE1E,uCAAuC;AACvC,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAW,CAAC;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAE5E,qBAAqB;AACrB,MAAM,CAAC,MAAM,MAAM,GAAG;IACrB,yCAAyC;IACzC,aAAa,EAAE,GAAG;IAClB,+BAA+B;IAC/B,cAAc,EAAE,GAAG;IACnB,wBAAwB;IACxB,aAAa,EAAE,IAAI;IACnB,wCAAwC;IACxC,iBAAiB,EAAE,GAAG;CACb,CAAC;AAEX,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAEH,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,YAAY;IACZ,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtF,WAAW;IACX,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAClD,iBAAiB;IACjB,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC;IAChD,kBAAkB;IAClB,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrF,0BAA0B;IAC1B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACjG;;;OAGG;IACH,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACvD,iBAAiB;IACjB,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,gCAAgC;IAChC,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC1C,CAAC,CAAC;AAKH,MAAM,UAAU,mBAAmB,CAAC,KAA2B;IAC9D,OAAO,oBAAoB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,uBAAuB;AACvB,MAAM,CAAC,MAAM,WAAW,GAAG,4BAA4B,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE1E,uCAAuC;AACvC,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAW,CAAC;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAE5E,qBAAqB;AACrB,MAAM,CAAC,MAAM,MAAM,GAAG;IACrB,yCAAyC;IACzC,aAAa,EAAE,GAAG;IAClB,+BAA+B;IAC/B,cAAc,EAAE,GAAG;IACnB,wBAAwB;IACxB,aAAa,EAAE,IAAI;IACnB,wCAAwC;IACxC,iBAAiB,EAAE,GAAG;CACb,CAAC;AAEX,0CAA0C;AAC1C,MAAM,WAAW,GAAG,CAAC;KACnB,MAAM,CAAC;IACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC;KACD,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAElC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,mCAAmC;IACnC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IAC3C,WAAW;IACX,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAClD,iBAAiB;IACjB,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC;IAChD,kBAAkB;IAClB,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrF,0BAA0B;IAC1B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACjG;;;OAGG;IACH,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACvD,iBAAiB;IACjB,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,gCAAgC;IAChC,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC1C,CAAC,CAAC;AAKH,MAAM,UAAU,mBAAmB,CAAC,KAA2B;IAC9D,OAAO,oBAAoB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,uBAAuB;AACvB,MAAM,CAAC,MAAM,WAAW,GAAG,4BAA4B,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { ReactElement } from "react";
2
+ import type { FreedrawShapeData, StrokePoint } from "./types.js";
3
+ /** 太さの範囲(world px)。 */
4
+ export interface PenSizeRange {
5
+ min: number;
6
+ max: number;
7
+ }
8
+ /** {@link FreedrawPenDefinition.finalize} の戻り値。 */
9
+ export interface FinalizedStroke {
10
+ /** 保存する点列(world 座標)。 */
11
+ points: StrokePoint[];
12
+ /**
13
+ * ペン固有の保存データ。shape の `penData` に入る。移動・拡大縮小では点列だけが
14
+ * 変わり、`penData` はそのまま写されるので、座標(点列から作った形など)は入れない。
15
+ */
16
+ penData?: Record<string, unknown>;
17
+ }
18
+ /**
19
+ * 外から足すペンの定義(`createFreedrawPlugin(config, { pens })` で渡す)。
20
+ *
21
+ * 足したペンのストロークも組み込みのペンと同じ `freedraw` shape になるので、選択・移動・
22
+ * 拡大縮小・消しゴム・当たり判定・undo はそのまま効く。描画は SVG(DOM)で行い、GPU には
23
+ * 回さない。ペンを登録していないクライアントでは、そのストロークはボールペンの線で描かれる。
24
+ */
25
+ export interface FreedrawPenDefinition {
26
+ /** shape の `pen` に入る id。組み込みのペン(ballpoint など)とは重ねない。 */
27
+ id: string;
28
+ label: string;
29
+ /** 既定の太さ(world px)。 */
30
+ defaultSize: number;
31
+ /** 太さの範囲。`freedraw:set-size` はこの範囲に丸める。省略時は丸めない。 */
32
+ sizeRange?: PenSizeRange;
33
+ /** 色を使うか(`false` ならペン先カーソルを色なしで出す)。既定 `true`。 */
34
+ usesColor?: boolean;
35
+ /** 確定したストロークの描画。 */
36
+ render(shape: FreedrawShapeData): ReactElement;
37
+ /** 描いている最中(`shape.draft === true`)の描画。省略時は {@link render}。 */
38
+ renderDraft?(shape: FreedrawShapeData): ReactElement;
39
+ /**
40
+ * 手を離したときに 1 回だけ呼ぶ。間引き後の点列を受け取り、保存する点列と
41
+ * ペン固有のデータを返す。省略時は点列をそのまま保存する。
42
+ */
43
+ finalize?(points: StrokePoint[], ctx: {
44
+ size: number;
45
+ }): FinalizedStroke;
46
+ /**
47
+ * 点列(中心線)から描画の端までの最大の距離。外接矩形・当たり判定・消しゴムに使う。
48
+ * 省略時は `size / 2`。
49
+ */
50
+ halfWidth?(size: number): number;
51
+ }
52
+ /** 組み込みのペンの id なら例外にする(登録より前に全部確かめるため分けている)。 */
53
+ export declare function assertCustomPenId(id: string): void;
54
+ /**
55
+ * ペンを登録する(freedraw プラグインの setup から呼ぶ)。同じ定義は登録した数だけ
56
+ * 数え、全部外れたら消す(同じランタイムの複数ボードで共有しても、1 つの teardown で
57
+ * 他のボードから消えない)。同じ id の別の定義は置き換える。戻り値で 1 回ぶん外す。
58
+ */
59
+ export declare function registerPen(def: FreedrawPenDefinition): () => void;
60
+ /** 登録済みのペン定義(組み込みのペンは含まない)。 */
61
+ export declare function getPenDefinition(id: string | undefined): FreedrawPenDefinition | undefined;
62
+ /** 登録済みのペン定義の一覧(登録順)。 */
63
+ export declare function listPenDefinitions(): FreedrawPenDefinition[];
64
+ /** 登録が変わったら呼ぶ。戻り値で解除。 */
65
+ export declare function onPensChange(listener: () => void): () => void;
66
+ /** `size` を定義の範囲に丸める(範囲が無ければそのまま)。 */
67
+ export declare function clampPenSize(def: FreedrawPenDefinition | undefined, size: number): number;
68
+ //# sourceMappingURL=custom-pens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-pens.d.ts","sourceRoot":"","sources":["../src/custom-pens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAW,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,uBAAuB;AACvB,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC/B,wBAAwB;IACxB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACrC,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB;IACpB,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAAC;IAC/C,8DAA8D;IAC9D,WAAW,CAAC,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,eAAe,CAAC;IACzE;;;OAGG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AAkBD,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAElD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAmBlE;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,qBAAqB,GAAG,SAAS,CAE1F;AAED,yBAAyB;AACzB,wBAAgB,kBAAkB,IAAI,qBAAqB,EAAE,CAE5D;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAK7D;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzF"}
@@ -0,0 +1,72 @@
1
+ // 登録は JS ランタイム単位(同じランタイムの AppInstance で共有)。shape の当たり判定や
2
+ // 外接矩形は shape だけを受け取る純関数から呼ばれるため、ここから引けるようにしている。
3
+ const registry = new Map();
4
+ // 組み込みのペンの id(pen-meta.ts の PEN_KINDS と同じ。循環 import を避けて自前で持つ)。
5
+ const BUILT_IN_IDS = new Set([
6
+ "ballpoint",
7
+ "felt",
8
+ "brush",
9
+ "highlighter",
10
+ ]);
11
+ const listeners = new Set();
12
+ const notify = () => {
13
+ for (const l of listeners)
14
+ l();
15
+ };
16
+ /** 組み込みのペンの id なら例外にする(登録より前に全部確かめるため分けている)。 */
17
+ export function assertCustomPenId(id) {
18
+ if (BUILT_IN_IDS.has(id))
19
+ throw new Error(`freedraw: "${id}" is a built-in pen id`);
20
+ }
21
+ /**
22
+ * ペンを登録する(freedraw プラグインの setup から呼ぶ)。同じ定義は登録した数だけ
23
+ * 数え、全部外れたら消す(同じランタイムの複数ボードで共有しても、1 つの teardown で
24
+ * 他のボードから消えない)。同じ id の別の定義は置き換える。戻り値で 1 回ぶん外す。
25
+ */
26
+ export function registerPen(def) {
27
+ assertCustomPenId(def.id);
28
+ const cur = registry.get(def.id);
29
+ if (cur && cur.def === def)
30
+ cur.count += 1;
31
+ else {
32
+ registry.set(def.id, { def, count: 1 });
33
+ notify();
34
+ }
35
+ let released = false;
36
+ return () => {
37
+ if (released)
38
+ return;
39
+ released = true;
40
+ const entry = registry.get(def.id);
41
+ if (!entry || entry.def !== def)
42
+ return;
43
+ entry.count -= 1;
44
+ if (entry.count > 0)
45
+ return;
46
+ registry.delete(def.id);
47
+ notify();
48
+ };
49
+ }
50
+ /** 登録済みのペン定義(組み込みのペンは含まない)。 */
51
+ export function getPenDefinition(id) {
52
+ return id === undefined ? undefined : registry.get(id)?.def;
53
+ }
54
+ /** 登録済みのペン定義の一覧(登録順)。 */
55
+ export function listPenDefinitions() {
56
+ return [...registry.values()].map((e) => e.def);
57
+ }
58
+ /** 登録が変わったら呼ぶ。戻り値で解除。 */
59
+ export function onPensChange(listener) {
60
+ listeners.add(listener);
61
+ return () => {
62
+ listeners.delete(listener);
63
+ };
64
+ }
65
+ /** `size` を定義の範囲に丸める(範囲が無ければそのまま)。 */
66
+ export function clampPenSize(def, size) {
67
+ const r = def?.sizeRange;
68
+ if (!r)
69
+ return size;
70
+ return Math.min(r.max, Math.max(r.min, size));
71
+ }
72
+ //# sourceMappingURL=custom-pens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-pens.js","sourceRoot":"","sources":["../src/custom-pens.ts"],"names":[],"mappings":"AAqDA,yDAAyD;AACzD,iDAAiD;AACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyD,CAAC;AAClF,gEAAgE;AAChE,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAU;IAC1D,WAAW;IACX,MAAM;IACN,OAAO;IACP,aAAa;CACb,CAAC,CAAC;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AAExC,MAAM,MAAM,GAAG,GAAG,EAAE;IACnB,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,CAAC,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC3C,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,GAA0B;IACrD,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG;QAAE,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;SACtC,CAAC;QACL,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,EAAE,CAAC;IACV,CAAC;IACD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,GAAG,EAAE;QACX,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG;YAAE,OAAO;QACxC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;YAAE,OAAO;QAC5B,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,EAAE,CAAC;IACV,CAAC,CAAC;AACH,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,gBAAgB,CAAC,EAAsB;IACtD,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC;AAC7D,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,kBAAkB;IACjC,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,YAAY,CAAC,QAAoB;IAChD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACX,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC,CAAC;AACH,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,YAAY,CAAC,GAAsC,EAAE,IAAY;IAChF,MAAM,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC;IACzB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type CanvasPointerEvent, type ToolContext } from "@edv4h/usketch-shared";
2
- import type { FreedrawSettingsStore } from "./settings-store.js";
2
+ import { type FreedrawSettingsStore } from "./settings-store.js";
3
3
  import type { PointerStore } from "./ui/cursor-overlay.js";
4
4
  export interface DrawController {
5
5
  onPointerDown(toolCtx: ToolContext, event: CanvasPointerEvent): void;
@@ -1 +1 @@
1
- {"version":3,"file":"draw-tool.d.ts","sourceRoot":"","sources":["../src/draw-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,EAIvB,KAAK,WAAW,EAChB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AA6C3D,MAAM,WAAW,cAAc;IAC9B,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrE,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnE,uBAAuB;IACvB,KAAK,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,YAAY,GACnB,cAAc,CAkLhB"}
1
+ {"version":3,"file":"draw-tool.d.ts","sourceRoot":"","sources":["../src/draw-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,EAIvB,KAAK,WAAW,EAChB,MAAM,uBAAuB,CAAC;AAS/B,OAAO,EAAE,KAAK,qBAAqB,EAAW,MAAM,qBAAqB,CAAC;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAyC3D,MAAM,WAAW,cAAc;IAC9B,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrE,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnE,uBAAuB;IACvB,KAAK,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,YAAY,GACnB,cAAc,CAuLhB"}
package/dist/draw-tool.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { DEFAULT_STYLE, generateId, } from "@edv4h/usketch-shared";
2
2
  import { createAddShapeCommand } from "@edv4h/usketch-store";
3
3
  import { TUNING } from "./config.js";
4
+ import { getPenDefinition } from "./custom-pens.js";
4
5
  import { createEraseStrokesCommand, findErasedStrokes } from "./eraser.js";
5
6
  import { smoothPressure, speedPressure } from "./geometry/brush-outline.js";
7
+ import { penHalfWidth } from "./geometry/hit.js";
6
8
  import { simplifyPoints } from "./geometry/simplify.js";
7
9
  import { penMeta } from "./pen-meta.js";
8
- function halfWidthForPen(variable, size) {
9
- return variable ? (size * 1.55) / 2 : size / 2;
10
- }
10
+ import { penSize } from "./settings-store.js";
11
11
  function boundsOf(points, pad) {
12
12
  let minX = Number.POSITIVE_INFINITY;
13
13
  let minY = Number.POSITIVE_INFINITY;
@@ -45,7 +45,7 @@ export function createDrawController(settings, pointer) {
45
45
  raf = 0;
46
46
  if (!stroke)
47
47
  return;
48
- const pad = halfWidthForPen(stroke.variable, stroke.size);
48
+ const pad = penHalfWidth(stroke.pen, stroke.size);
49
49
  const b = boundsOf(stroke.points, pad);
50
50
  toolCtx.store.updateShape(stroke.id, {
51
51
  x: b.x,
@@ -80,7 +80,7 @@ export function createDrawController(settings, pointer) {
80
80
  return;
81
81
  }
82
82
  const pen = s.pen;
83
- const size = s.sizes[pen];
83
+ const size = penSize(s, pen);
84
84
  const m = penMeta(pen);
85
85
  const id = generateId();
86
86
  const first = {
@@ -111,6 +111,7 @@ export function createDrawController(settings, pointer) {
111
111
  style: buildStyle(s.color, size, m.alpha),
112
112
  points: [first],
113
113
  pen,
114
+ draft: true,
114
115
  };
115
116
  toolCtx.store.addShape(shape);
116
117
  },
@@ -170,10 +171,14 @@ export function createDrawController(settings, pointer) {
170
171
  }
171
172
  const cur = stroke;
172
173
  stroke = null;
173
- // 確定: scratch を削除 → 間引き → undo 可能な追加コマンド。
174
+ // 確定: scratch を削除 → 間引き →(外から足したペンは finalize)→ undo 可能な追加コマンド。
174
175
  toolCtx.store.deleteShape(cur.id);
175
- const points = simplifyPoints(cur.points, TUNING.simplifyTolerance);
176
- const pad = halfWidthForPen(cur.variable, cur.size);
176
+ const simplified = simplifyPoints(cur.points, TUNING.simplifyTolerance);
177
+ const finalized = getPenDefinition(cur.pen)?.finalize?.(simplified, { size: cur.size });
178
+ const points = finalized?.points ?? simplified;
179
+ if (points.length === 0)
180
+ return;
181
+ const pad = penHalfWidth(cur.pen, cur.size);
177
182
  const b = boundsOf(points, pad);
178
183
  const shape = {
179
184
  id: cur.id,
@@ -185,6 +190,7 @@ export function createDrawController(settings, pointer) {
185
190
  style: buildStyle(cur.color, cur.size, cur.alpha),
186
191
  points,
187
192
  pen: cur.pen,
193
+ ...(finalized?.penData ? { penData: finalized.penData } : {}),
188
194
  };
189
195
  toolCtx.commands.execute(createAddShapeCommand(toolCtx.store, shape));
190
196
  },
@@ -1 +1 @@
1
- {"version":3,"file":"draw-tool.js","sourceRoot":"","sources":["../src/draw-tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"draw-tool.js","sourceRoot":"","sources":["../src/draw-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type ServiceRegistry } from "@edv4h/usketch-shared";
2
+ import { type PenSizeRange } from "./custom-pens.js";
3
+ import type { PenId } from "./types.js";
4
+ /** ペン選択 UI 向けの、ペン 1 種の情報。 */
5
+ export interface FreedrawPenInfo {
6
+ id: PenId;
7
+ label: string;
8
+ defaultSize: number;
9
+ sizeRange?: PenSizeRange;
10
+ /** 色を使うか。 */
11
+ usesColor: boolean;
12
+ /** 組み込みのペンか。 */
13
+ builtIn: boolean;
14
+ }
15
+ export interface FreedrawApi {
16
+ /** 選べるペン(組み込み → 外から足したペンの登録順)。 */
17
+ listPens(): FreedrawPenInfo[];
18
+ /** ペンの登録が変わったら呼ぶ。戻り値で解除。 */
19
+ onPensChange(listener: () => void): () => void;
20
+ }
21
+ /** 組み込み + 登録済みのペンの一覧。 */
22
+ export declare function listPens(): FreedrawPenInfo[];
23
+ export declare const freedrawApi: FreedrawApi;
24
+ /** freedraw の API のサービス。`setup` で provide する。 */
25
+ export declare const freedrawService: import("@edv4h/usketch-shared").ServiceHandle<FreedrawApi>;
26
+ /** ホスト用: `getFreedrawApi(app.services)?.listPens()`。freedraw が無ければ `undefined`。 */
27
+ export declare function getFreedrawApi(services: ServiceRegistry): FreedrawApi | undefined;
28
+ //# sourceMappingURL=freedraw-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freedraw-service.d.ts","sourceRoot":"","sources":["../src/freedraw-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,6BAA6B;AAC7B,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,aAAa;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB;IAChB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,kCAAkC;IAClC,QAAQ,IAAI,eAAe,EAAE,CAAC;IAC9B,4BAA4B;IAC5B,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC/C;AAED,yBAAyB;AACzB,wBAAgB,QAAQ,IAAI,eAAe,EAAE,CAiB5C;AAED,eAAO,MAAM,WAAW,EAAE,WAAwC,CAAC;AAEnE,iDAAiD;AACjD,eAAO,MAAM,eAAe,4DAA8D,CAAC;AAE3F,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,WAAW,GAAG,SAAS,CAEjF"}
@@ -0,0 +1,32 @@
1
+ // freedraw のホスト向け API(`ctx.services`)。ペンの一覧を読む(ペンを足すのは
2
+ // `createFreedrawPlugin(config, { pens })`)。
3
+ import { defineService } from "@edv4h/usketch-shared";
4
+ import { listPenDefinitions, onPensChange } from "./custom-pens.js";
5
+ import { PEN_KINDS, PEN_META } from "./pen-meta.js";
6
+ /** 組み込み + 登録済みのペンの一覧。 */
7
+ export function listPens() {
8
+ const builtIn = PEN_KINDS.map((id) => ({
9
+ id,
10
+ label: PEN_META[id].label,
11
+ defaultSize: PEN_META[id].defaultSize,
12
+ usesColor: true,
13
+ builtIn: true,
14
+ }));
15
+ const custom = listPenDefinitions().map((d) => ({
16
+ id: d.id,
17
+ label: d.label,
18
+ defaultSize: d.defaultSize,
19
+ ...(d.sizeRange ? { sizeRange: d.sizeRange } : {}),
20
+ usesColor: d.usesColor !== false,
21
+ builtIn: false,
22
+ }));
23
+ return [...builtIn, ...custom];
24
+ }
25
+ export const freedrawApi = { listPens, onPensChange };
26
+ /** freedraw の API のサービス。`setup` で provide する。 */
27
+ export const freedrawService = defineService("usketch-plugin-shape-freedraw");
28
+ /** ホスト用: `getFreedrawApi(app.services)?.listPens()`。freedraw が無ければ `undefined`。 */
29
+ export function getFreedrawApi(services) {
30
+ return freedrawService.get(services);
31
+ }
32
+ //# sourceMappingURL=freedraw-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freedraw-service.js","sourceRoot":"","sources":["../src/freedraw-service.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,6CAA6C;AAC7C,OAAO,EAAE,aAAa,EAAwB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAqB,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAsBpD,yBAAyB;AACzB,MAAM,UAAU,QAAQ;IACvB,MAAM,OAAO,GAAsB,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACzD,EAAE;QACF,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK;QACzB,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW;QACrC,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;KACb,CAAC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAsB,kBAAkB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,SAAS,EAAE,CAAC,CAAC,SAAS,KAAK,KAAK;QAChC,OAAO,EAAE,KAAK;KACd,CAAC,CAAC,CAAC;IACJ,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAgB,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAEnE,iDAAiD;AACjD,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAc,+BAA+B,CAAC,CAAC;AAE3F,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,QAAyB;IACvD,OAAO,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC"}
@@ -1,5 +1,10 @@
1
1
  import type { BoundingBox, Point } from "@edv4h/usketch-shared";
2
- import type { FreedrawShapeData } from "../types.js";
2
+ import type { FreedrawShapeData, PenId } from "../types.js";
3
+ /**
4
+ * ペンの最大半幅(world px)。外から足したペンは `halfWidth`(省略時 size/2)、
5
+ * 可変ペンは size×1.55/2、一定ペンは size/2。
6
+ */
7
+ export declare function penHalfWidth(pen: PenId | undefined, size: number): number;
3
8
  /** ストロークの最大半幅。 */
4
9
  export declare function maxHalfWidth(data: FreedrawShapeData): number;
5
10
  /** 点列 + 最大半幅で bbox を算出(細い線でも掴める)。 */
@@ -1 +1 @@
1
- {"version":3,"file":"hit.d.ts","sourceRoot":"","sources":["../../src/geometry/hit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAwB,MAAM,aAAa,CAAC;AAc3E,kBAAkB;AAClB,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAI5D;AAED,qCAAqC;AACrC,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,WAAW,CAsBjE;AAgBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,SAAI,GAAG,OAAO,CAkBvF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAUrF"}
1
+ {"version":3,"file":"hit.d.ts","sourceRoot":"","sources":["../../src/geometry/hit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAe,MAAM,aAAa,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzE;AAgBD,kBAAkB;AAClB,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAE5D;AAED,qCAAqC;AACrC,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,WAAW,CAsBjE;AAoED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,SAAI,GAAG,OAAO,CAuBvF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAcrF"}
@@ -1,20 +1,31 @@
1
+ import { getPenDefinition } from "../custom-pens.js";
1
2
  import { penMeta } from "../pen-meta.js";
2
- /** 点ごとの実効半幅(world px)。可変ペンは p×size、一定ペンは size 基準。 */
3
- function halfWidthAt(pt, pen, size) {
4
- const m = penMeta(pen);
5
- if (m.variable) {
6
- const min = Math.max(0.6, size * 0.22);
7
- const max = size * 1.55;
8
- const w = min + (max - min) * (pt.p ?? 0.5);
9
- return w / 2;
3
+ /**
4
+ * ペンの最大半幅(world px)。外から足したペンは `halfWidth`(省略時 size/2)、
5
+ * 可変ペンは size×1.55/2、一定ペンは size/2。
6
+ */
7
+ export function penHalfWidth(pen, size) {
8
+ const custom = getPenDefinition(pen);
9
+ if (custom)
10
+ return custom.halfWidth ? custom.halfWidth(size) : size / 2;
11
+ return penMeta(pen).variable ? (size * 1.55) / 2 : size / 2;
12
+ }
13
+ /**
14
+ * 点ごとの実効半幅(world px)を返す関数。可変ペンは p×size、それ以外は点によらず一定。
15
+ * ペンの解決はストロークごとに 1 回だけにする(点のループの外で呼ぶ)。
16
+ */
17
+ function halfWidthFn(pen, size) {
18
+ if (getPenDefinition(pen) || !penMeta(pen).variable) {
19
+ const half = penHalfWidth(pen, size);
20
+ return () => half;
10
21
  }
11
- return size / 2;
22
+ const min = Math.max(0.6, size * 0.22);
23
+ const max = size * 1.55;
24
+ return (pt) => (min + (max - min) * (pt.p ?? 0.5)) / 2;
12
25
  }
13
26
  /** ストロークの最大半幅。 */
14
27
  export function maxHalfWidth(data) {
15
- const size = data.style?.strokeWidth ?? 1;
16
- const m = penMeta(data.pen);
17
- return m.variable ? (size * 1.55) / 2 : size / 2;
28
+ return penHalfWidth(data.pen, data.style?.strokeWidth ?? 1);
18
29
  }
19
30
  /** 点列 + 最大半幅で bbox を算出(細い線でも掴める)。 */
20
31
  export function strokeBounds(data) {
@@ -44,6 +55,50 @@ export function strokeBounds(data) {
44
55
  height: maxY - minY + pad * 2,
45
56
  };
46
57
  }
58
+ // ストアは未変更の shape のオブジェクト参照を保つ(更新は新オブジェクトに差し替え)ので、
59
+ // shape 参照をキーにすれば、ホバーや消しゴムのドラッグ中に同じストロークの範囲を作り直さずに済む。
60
+ const strokeReachCache = new WeakMap();
61
+ /** {@link StrokeReach} をキャッシュ付きで返す。点が無ければ null。 */
62
+ function strokeReach(data) {
63
+ const cached = strokeReachCache.get(data);
64
+ if (cached !== undefined)
65
+ return cached;
66
+ const points = data.points ?? [];
67
+ const size = data.style?.strokeWidth ?? 1;
68
+ let minX = Number.POSITIVE_INFINITY;
69
+ let minY = Number.POSITIVE_INFINITY;
70
+ let maxX = Number.NEGATIVE_INFINITY;
71
+ let maxY = Number.NEGATIVE_INFINITY;
72
+ let maxHalf = 0;
73
+ const halfWidthAt = halfWidthFn(data.pen, size);
74
+ for (const pt of points) {
75
+ if (pt.x < minX)
76
+ minX = pt.x;
77
+ if (pt.y < minY)
78
+ minY = pt.y;
79
+ if (pt.x > maxX)
80
+ maxX = pt.x;
81
+ if (pt.y > maxY)
82
+ maxY = pt.y;
83
+ const half = halfWidthAt(pt);
84
+ if (half > maxHalf)
85
+ maxHalf = half;
86
+ }
87
+ const reach = points.length === 0
88
+ ? null
89
+ : { minX: minX - maxHalf, minY: minY - maxHalf, maxX: maxX + maxHalf, maxY: maxY + maxHalf };
90
+ strokeReachCache.set(data, reach);
91
+ return reach;
92
+ }
93
+ /** `point` が {@link StrokeReach} を `margin` だけ広げた箱の外にあれば true(点が無いときも true)。 */
94
+ function outsideReach(data, point, margin) {
95
+ const reach = strokeReach(data);
96
+ return (reach === null ||
97
+ point.x < reach.minX - margin ||
98
+ point.x > reach.maxX + margin ||
99
+ point.y < reach.minY - margin ||
100
+ point.y > reach.maxY + margin);
101
+ }
47
102
  /** 点 p から線分 ab までの距離の2乗。 */
48
103
  function distToSegment2(p, a, b) {
49
104
  const dx = b.x - a.x;
@@ -66,8 +121,14 @@ export function hitStroke(data, point, tolerance = 2) {
66
121
  const size = data.style?.strokeWidth ?? 1;
67
122
  if (points.length === 0)
68
123
  return false;
124
+ // ホバーは毎 pointermove で盤面の全ストロークに対して呼ばれる。線分ごとの判定半径
125
+ // (両端の半幅の大きい方 + tolerance)は「点の範囲を最大半幅で広げた箱」を tolerance だけ
126
+ // 広げた外には届かないので、箱の外なら線分を調べずに false を返す。
127
+ if (outsideReach(data, point, tolerance))
128
+ return false;
129
+ const halfWidthAt = halfWidthFn(data.pen, size);
69
130
  if (points.length === 1) {
70
- const r = halfWidthAt(points[0], data.pen, size) + tolerance;
131
+ const r = halfWidthAt(points[0]) + tolerance;
71
132
  const dx = point.x - points[0].x;
72
133
  const dy = point.y - points[0].y;
73
134
  return dx * dx + dy * dy <= r * r;
@@ -75,7 +136,7 @@ export function hitStroke(data, point, tolerance = 2) {
75
136
  for (let i = 1; i < points.length; i++) {
76
137
  const a = points[i - 1];
77
138
  const b = points[i];
78
- const half = Math.max(halfWidthAt(a, data.pen, size), halfWidthAt(b, data.pen, size));
139
+ const half = Math.max(halfWidthAt(a), halfWidthAt(b));
79
140
  const r = half + tolerance;
80
141
  if (distToSegment2(point, a, b) <= r * r)
81
142
  return true;
@@ -88,9 +149,14 @@ export function hitStroke(data, point, tolerance = 2) {
88
149
  */
89
150
  export function eraserHits(data, cursor, r) {
90
151
  const points = data.points ?? [];
152
+ // 点ごとの判定 |pt − cursor| ≤ r + half は、各軸で |pt − cursor| ≤ r + half を含意する。
153
+ // 箱(点の範囲を最大半幅で広げたもの)を r だけ広げた外にカーソルがあれば、どの点も当たらない。
154
+ if (outsideReach(data, cursor, r))
155
+ return false;
91
156
  const size = data.style?.strokeWidth ?? 1;
157
+ const halfWidthAt = halfWidthFn(data.pen, size);
92
158
  for (const pt of points) {
93
- const half = halfWidthAt(pt, data.pen, size);
159
+ const half = halfWidthAt(pt);
94
160
  const dx = pt.x - cursor.x;
95
161
  const dy = pt.y - cursor.y;
96
162
  if (Math.hypot(dx, dy) <= r + half)