mudlet-map-renderer 1.0.0 → 1.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.
Files changed (106) hide show
  1. package/README.md +520 -0
  2. package/dist/AreaMapRenderer.d.ts +125 -0
  3. package/dist/CullingManager.d.ts +15 -0
  4. package/dist/ExitRenderer.d.ts +109 -0
  5. package/dist/InteractionHandler.d.ts +47 -0
  6. package/dist/MapGraph.d.ts +28 -0
  7. package/dist/MapReader-mU_4JWv_.js +224 -0
  8. package/dist/MapReader-mU_4JWv_.js.map +1 -0
  9. package/dist/MapState.d.ts +110 -0
  10. package/dist/PathData.d.ts +18 -0
  11. package/dist/PathFinder.d.ts +12 -0
  12. package/dist/ScenePipeline.d.ts +226 -0
  13. package/dist/SvgTypes.d.ts +21 -0
  14. package/dist/TypedEventEmitter.d.ts +17 -0
  15. package/dist/binary/BinaryMapReader.d.ts +36 -0
  16. package/dist/binary/index.d.ts +2 -0
  17. package/dist/binary.mjs +34 -0
  18. package/dist/binary.mjs.map +1 -0
  19. package/dist/camera/Camera.d.ts +118 -0
  20. package/dist/coord/CoordFn.d.ts +13 -0
  21. package/dist/directions.d.ts +25 -0
  22. package/dist/draw/DrawCommand.d.ts +104 -0
  23. package/dist/draw/DrawCommandBuilder.d.ts +19 -0
  24. package/dist/export/CanvasExporter.d.ts +71 -0
  25. package/dist/export/Exporter.d.ts +58 -0
  26. package/dist/export/PngExporter.d.ts +23 -0
  27. package/dist/export/SvgExporter.d.ts +19 -0
  28. package/dist/export/canvasToBytes.d.ts +19 -0
  29. package/dist/export/clipSceneToViewport.d.ts +48 -0
  30. package/dist/export/flushSceneShapes.d.ts +21 -0
  31. package/dist/export/sceneBounds.d.ts +24 -0
  32. package/dist/hit/HitTester.d.ts +101 -0
  33. package/dist/index.d.ts +61 -0
  34. package/dist/index.mjs +6670 -0
  35. package/dist/index.mjs.map +1 -0
  36. package/dist/lens/ExplorationLens.d.ts +29 -0
  37. package/dist/lens/RoomLens.d.ts +47 -0
  38. package/dist/lens/composeLenses.d.ts +31 -0
  39. package/dist/lens/index.d.ts +5 -0
  40. package/dist/overlay/AmbientLightOverlay.d.ts +32 -0
  41. package/dist/overlay/LiveEffect.d.ts +33 -0
  42. package/dist/overlay/SceneOverlay.d.ts +68 -0
  43. package/dist/reader/Area.d.ts +63 -0
  44. package/dist/reader/Exit.d.ts +15 -0
  45. package/dist/reader/MapReader.d.ts +34 -0
  46. package/dist/reader/Plane.d.ts +33 -0
  47. package/dist/render/CanvasRenderer.d.ts +17 -0
  48. package/dist/render/RecordingLayer.d.ts +158 -0
  49. package/dist/render/SvgRenderer.d.ts +7 -0
  50. package/dist/render/shapeToRecording.d.ts +3 -0
  51. package/dist/rendering/KonvaRenderBackend.d.ts +122 -0
  52. package/dist/rendering/MapRenderer.d.ts +213 -0
  53. package/dist/rendering/SceneManager.d.ts +54 -0
  54. package/dist/scene/AmbientLightStyle.d.ts +29 -0
  55. package/dist/scene/GridStyle.d.ts +21 -0
  56. package/dist/scene/InnerExitStyle.d.ts +24 -0
  57. package/dist/scene/OverlayStyle.d.ts +47 -0
  58. package/dist/scene/RoomStyle.d.ts +32 -0
  59. package/dist/scene/Shape.d.ts +151 -0
  60. package/dist/scene/SpecialExitStyle.d.ts +37 -0
  61. package/dist/scene/StubStyle.d.ts +15 -0
  62. package/dist/scene/elements/ExitLayout.d.ts +22 -0
  63. package/dist/scene/elements/GridLayout.d.ts +24 -0
  64. package/dist/scene/elements/LabelLayout.d.ts +11 -0
  65. package/dist/scene/elements/OverlayLayout.d.ts +14 -0
  66. package/dist/scene/elements/RoomLayout.d.ts +19 -0
  67. package/dist/scene/elements/SpecialExitLayout.d.ts +19 -0
  68. package/dist/scene/elements/StubLayout.d.ts +19 -0
  69. package/dist/style/Style.d.ts +60 -0
  70. package/dist/style/applyStyle.d.ts +3 -0
  71. package/dist/style/index.d.ts +21 -0
  72. package/dist/style/shape/BlueprintStyle.d.ts +11 -0
  73. package/dist/style/shape/ConstructionStyle.d.ts +17 -0
  74. package/dist/style/shape/IsometricStyle.d.ts +32 -0
  75. package/dist/style/shape/NeonStyle.d.ts +17 -0
  76. package/dist/style/shape/ParchmentStyle.d.ts +13 -0
  77. package/dist/style/shape/SciFiStyle.d.ts +16 -0
  78. package/dist/style/shape/SketchyStyle.d.ts +22 -0
  79. package/dist/style/shape/index.d.ts +25 -0
  80. package/dist/style/shape/paintMap.d.ts +25 -0
  81. package/dist/style/shape/wobble.d.ts +24 -0
  82. package/{src/types/MapData.ts → dist/types/MapData.d.ts} +70 -90
  83. package/dist/types/Settings.d.ts +206 -0
  84. package/dist/utils/color.d.ts +12 -0
  85. package/dist/utils/textMeasure.d.ts +38 -0
  86. package/package.json +67 -37
  87. package/demo/colors.json +0 -1
  88. package/demo/index.html +0 -102
  89. package/demo/main.ts +0 -389
  90. package/demo/mapExport.json +0 -1
  91. package/demo/tsconfig.json +0 -11
  92. package/src/ExitRenderer.ts +0 -275
  93. package/src/PathFinder.ts +0 -93
  94. package/src/PathRenderer.ts +0 -129
  95. package/src/Renderer.ts +0 -374
  96. package/src/directions.ts +0 -66
  97. package/src/index.ts +0 -4
  98. package/src/reader/Area.ts +0 -96
  99. package/src/reader/Exit.ts +0 -36
  100. package/src/reader/ExplorationArea.ts +0 -132
  101. package/src/reader/MapReader.ts +0 -123
  102. package/src/reader/Plane.ts +0 -42
  103. package/tsconfig.json +0 -17
  104. package/vercel.json +0 -5
  105. package/vite.config.ts +0 -29
  106. package/vite.demo.config.ts +0 -15
@@ -0,0 +1,226 @@
1
+ import { IMapReader } from './reader/MapReader';
2
+ import { IArea } from './reader/Area';
3
+ import { IPlane } from './reader/Plane';
4
+ import { Settings } from './types/Settings';
5
+ import { default as ExitRenderer, ExitDrawData } from './ExitRenderer';
6
+ import { GroupShape, Shape } from './scene/Shape';
7
+ import { RoomLens } from './lens/RoomLens';
8
+ type Bounds = {
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ };
14
+ /**
15
+ * Reference to one room's body shape inside the scene. Keyed by roomId so
16
+ * downstream consumers (cull index, hit-test bookkeeping) can find a room
17
+ * shape by id without re-walking the scene tree.
18
+ */
19
+ export type RoomShapeRef = {
20
+ room: MapData.Room;
21
+ shape: GroupShape;
22
+ };
23
+ /**
24
+ * Reference to one drawn link-exit shape, paired with its world-space bounds
25
+ * and (optional) cross-area target room. Used by the live renderer to hang
26
+ * cull entries on each exit.
27
+ */
28
+ export type StandaloneExitShapeRef = {
29
+ shape: GroupShape;
30
+ bounds: Bounds;
31
+ targetRoomId?: number;
32
+ };
33
+ export type AreaExitHitZone = {
34
+ bounds: Bounds;
35
+ targetRoomId: number;
36
+ /** Source room center — used to compute arrow direction for labels. Optional for back-compat. */
37
+ from?: {
38
+ x: number;
39
+ y: number;
40
+ };
41
+ /** Arrow tip / far endpoint — anchor for placed labels. Optional for back-compat. */
42
+ tip?: {
43
+ x: number;
44
+ y: number;
45
+ };
46
+ /** Stroke colour of the rendered arrow — used to colour area-exit labels. */
47
+ arrowColor?: string;
48
+ };
49
+ /**
50
+ * One drawn two-way or one-way inter-room exit, with stable identity and the
51
+ * exact geometry ExitRenderer produced. Consumers (e.g. an editor's
52
+ * hit-testing layer) can run segment distance checks against
53
+ * `data.lines[].points` / `data.arrows[].points` to match exactly what the
54
+ * user sees — including dash patterns and the renderer's suppression rules
55
+ * (e.g. both-sides-customLine two-ways, one-ways overridden by customLine).
56
+ */
57
+ export type DrawnExitEntry = {
58
+ readonly a: number;
59
+ readonly b: number;
60
+ readonly aDir?: MapData.direction;
61
+ readonly bDir?: MapData.direction;
62
+ readonly kind: "exit" | "specialExit";
63
+ readonly zIndex: number[];
64
+ readonly data: ExitDrawData;
65
+ };
66
+ /**
67
+ * One drawn custom-line (special exit) polyline, as it was rendered for
68
+ * this scene. `points` is the flat [x,y,x,y,...] polyline with the source
69
+ * room's centre prepended (mirroring what the renderer actually drew), in
70
+ * render-space coordinates.
71
+ */
72
+ export type DrawnSpecialExitEntry = {
73
+ readonly roomId: number;
74
+ readonly exitName: string;
75
+ readonly points: number[];
76
+ readonly stroke: string;
77
+ readonly strokeWidth: number;
78
+ readonly dash?: number[];
79
+ readonly hasArrow: boolean;
80
+ readonly arrowTip?: {
81
+ x: number;
82
+ y: number;
83
+ };
84
+ readonly bounds: Bounds;
85
+ };
86
+ /**
87
+ * One drawn stub — a room's one-way exit indicator (the short line sticking
88
+ * out of the edge for every entry in `room.stubs`). Rendered directly from
89
+ * these coordinates by {@link ScenePipeline}, so hit-testing against them
90
+ * matches what's on screen. Non-planar stubs (up/down/in/out) are still
91
+ * recorded — x1==x2 and y1==y2 — so consumers can filter them out.
92
+ */
93
+ export type DrawnStubEntry = {
94
+ readonly roomId: number;
95
+ readonly direction: MapData.direction;
96
+ readonly x1: number;
97
+ readonly y1: number;
98
+ readonly x2: number;
99
+ readonly y2: number;
100
+ readonly stroke: string;
101
+ readonly strokeWidth: number;
102
+ };
103
+ /**
104
+ * World-space shapes for each logical layer. Same content the backend layer
105
+ * nodes received, but as plain SceneIR data — consumed by exporters that drive
106
+ * {@link buildDrawCommands} → engine renderers without going through a
107
+ * {@link DrawingBackend}.
108
+ *
109
+ * Order within each list mirrors the order in which the corresponding layer
110
+ * node received its `addNode` calls: e.g. `link` is labels → link exits → for
111
+ * each room (special exits, stubs); `room` is rooms → area name → area-exit
112
+ * labels.
113
+ */
114
+ export type SceneShapesByLayer = {
115
+ grid: Shape[];
116
+ link: Shape[];
117
+ room: Shape[];
118
+ topLabel: Shape[];
119
+ };
120
+ /** User-defined label shape paired with its world-space bounds (for culling). */
121
+ export type LabelShapeRef = {
122
+ shape: GroupShape;
123
+ bounds: Bounds;
124
+ };
125
+ /** Custom-line (special-exit) shape paired with its world-space bounds (for culling). */
126
+ export type SpecialExitShapeRef = {
127
+ shape: GroupShape;
128
+ bounds: Bounds;
129
+ };
130
+ /** Stub shape paired with its world-space bounds (for culling). */
131
+ export type StubShapeRef = {
132
+ shape: GroupShape;
133
+ bounds: Bounds;
134
+ };
135
+ /** Area-exit label shape paired with its world-space bounds (for culling). */
136
+ export type AreaExitLabelShapeRef = {
137
+ shape: GroupShape;
138
+ bounds: Bounds;
139
+ };
140
+ export type SceneBuildResult = {
141
+ /** Room body shapes keyed by roomId — for cull-entry construction. */
142
+ roomShapeRefs: Map<number, RoomShapeRef>;
143
+ /** Link-exit shapes paired with bounds and area-target metadata. */
144
+ standaloneExitShapeRefs: StandaloneExitShapeRef[];
145
+ /** Non-noScaling label shapes paired with world-space bounds (for culling). */
146
+ labelShapeRefs: LabelShapeRef[];
147
+ /** Custom-line special-exit shapes paired with world-space bounds (for culling). */
148
+ specialExitShapeRefs: SpecialExitShapeRef[];
149
+ /** Stub shapes paired with world-space bounds (for culling). */
150
+ stubShapeRefs: StubShapeRef[];
151
+ /** Area-exit label shapes paired with world-space bounds (for culling). */
152
+ areaExitLabelShapeRefs: AreaExitLabelShapeRef[];
153
+ areaExitHitZones: AreaExitHitZone[];
154
+ drawnExits: DrawnExitEntry[];
155
+ drawnSpecialExits: DrawnSpecialExitEntry[];
156
+ drawnStubs: DrawnStubEntry[];
157
+ /** World-space shapes carrying {@link HitInfo} annotations — fed to {@link HitTester}. */
158
+ hitShapes: Shape[];
159
+ /**
160
+ * Engine-agnostic shape lists per logical layer. Drives
161
+ * {@link buildDrawCommands} + a per-engine renderer.
162
+ */
163
+ sceneShapes: SceneShapesByLayer;
164
+ };
165
+ /**
166
+ * Engine-neutral scene composition pipeline.
167
+ *
168
+ * Walks a {@link MapData} area/plane and emits world-space {@link Shape}s per
169
+ * logical layer (grid / link / room / topLabel) plus the metadata downstream
170
+ * consumers need (cull entries, hit zones, drawn-geometry snapshots).
171
+ *
172
+ * The pipeline knows nothing about Konva, SVG, Canvas, or the
173
+ * {@link DrawCommandBuilder}: callers run the shape lists through whatever
174
+ * renderer fits their target. Both the interactive
175
+ * {@link KonvaRenderBackend} and the exporters consume the same
176
+ * {@link SceneBuildResult} this pipeline produces.
177
+ */
178
+ export declare class ScenePipeline {
179
+ private readonly mapReader;
180
+ private readonly settings;
181
+ readonly exitRenderer: ExitRenderer;
182
+ private linkShapes;
183
+ private roomShapes;
184
+ private topLabelShapes;
185
+ private labelShapeRefs;
186
+ private specialExitShapeRefs;
187
+ private stubShapeRefs;
188
+ private areaExitLabelShapeRefs;
189
+ constructor(mapReader: IMapReader, settings: Settings);
190
+ /**
191
+ * Build the full scene for an area/plane.
192
+ * Clears layers, renders grid → labels → exits → rooms → area name.
193
+ * Returns data for culling and interaction (room nodes, exit data, hit zones).
194
+ *
195
+ * The `lens` filters which rooms paint and how partially-visible exits are
196
+ * treated. Pass {@link ALL_VISIBLE} (or omit) for an unfiltered build.
197
+ */
198
+ buildScene(area: IArea, plane: IPlane, zIndex: number, lens?: RoomLens): SceneBuildResult;
199
+ getEffectiveBounds(area: IArea, plane: IPlane): {
200
+ minX: number;
201
+ maxX: number;
202
+ minY: number;
203
+ maxY: number;
204
+ };
205
+ private renderRooms;
206
+ private renderLinkExits;
207
+ /**
208
+ * Build a stub anchored at the visible endpoint of an exit, pointing
209
+ * toward the hidden one. Returns undefined when the exit can't be drawn
210
+ * as a stub (no planar direction on the visible side, both sides hidden,
211
+ * or both sides visible — the last is a caller bug).
212
+ */
213
+ private buildLensStub;
214
+ private emitLensStub;
215
+ private getRoomEdgePoint;
216
+ /**
217
+ * Build the world-space shape tree for one inter-room exit. Used by the
218
+ * live renderer's current-room overlay path to recolour a single exit
219
+ * without rebuilding the whole scene.
220
+ */
221
+ buildExitShape(data: ExitDrawData): GroupShape;
222
+ private renderLabels;
223
+ private renderAreaExitLabels;
224
+ private renderAreaName;
225
+ }
226
+ export {};
@@ -0,0 +1,21 @@
1
+ export type SvgOverlays = {
2
+ position?: {
3
+ roomId: number;
4
+ };
5
+ highlights?: Array<{
6
+ roomId: number;
7
+ color: string;
8
+ }>;
9
+ paths?: Array<{
10
+ locations: number[];
11
+ color: string;
12
+ }>;
13
+ };
14
+ export type SvgExportOptions = {
15
+ /** Room ID to center the export on. If omitted, exports the full area. */
16
+ roomId?: number;
17
+ /** Padding in map units around the exported region. Default: 3 */
18
+ padding?: number;
19
+ /** Overlay data (position marker, highlights, paths) to include in the export. */
20
+ overlays?: SvgOverlays;
21
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Lightweight typed event emitter.
3
+ * Also dispatches DOM CustomEvents on an optional container element
4
+ * for backwards compatibility.
5
+ */
6
+ export declare class TypedEventEmitter<EventMap extends Record<string, unknown>> {
7
+ private listeners;
8
+ private container?;
9
+ /**
10
+ * @param container Optional DOM element to also dispatch CustomEvents on (for backwards compat)
11
+ */
12
+ constructor(container?: HTMLElement);
13
+ on<K extends keyof EventMap>(event: K, handler: (detail: EventMap[K]) => void): void;
14
+ off<K extends keyof EventMap>(event: K, handler: (detail: EventMap[K]) => void): void;
15
+ removeAllListeners(): void;
16
+ emit<K extends keyof EventMap>(event: K, detail: EventMap[K]): void;
17
+ }
@@ -0,0 +1,36 @@
1
+ import { MudletMap, readMapFromBuffer } from 'mudlet-map-binary-reader';
2
+ import { IMapReader } from '../reader/MapReader';
3
+ import { IArea } from '../reader/Area';
4
+ /**
5
+ * {@link IMapReader} implementation backed by a parsed Mudlet binary map.
6
+ *
7
+ * Convenience wrapper around the existing {@link MapReader} that converts a
8
+ * {@link MudletMap} (the in-memory binary model from
9
+ * `mudlet-map-binary-reader`) into the renderer's `{mapData, colors}` shape
10
+ * via `readerExport()`, then forwards every `IMapReader` call to the wrapped
11
+ * reader.
12
+ *
13
+ * Useful for downstream apps (the upstream Mudix client is one) that already
14
+ * own binary `.dat` bytes and want a single object they can hand to
15
+ * {@link MapRenderer} without staging a separate JSON export step.
16
+ *
17
+ * `mudlet-map-binary-reader` is a `peerDependency`; consumers who do not use
18
+ * binary maps never pay the bundle cost.
19
+ */
20
+ export default class BinaryMapReader implements IMapReader {
21
+ private readonly reader;
22
+ /** Build directly from a parsed {@link MudletMap}. */
23
+ constructor(model: MudletMap);
24
+ /**
25
+ * Parse the given binary map buffer and construct a reader from it.
26
+ * In Node, pass `fs.readFileSync(path)`; in the browser, construct a
27
+ * `Buffer` from an `ArrayBuffer` (e.g. via the `buffer` polyfill).
28
+ */
29
+ static fromBuffer(buf: Parameters<typeof readMapFromBuffer>[0]): BinaryMapReader;
30
+ getArea(areaId: number): IArea;
31
+ getAreas(): IArea[];
32
+ getRooms(): MapData.Room[];
33
+ getRoom(roomId: number): MapData.Room;
34
+ getColorValue(envId: number): string;
35
+ getSymbolColor(envId: number, opacity?: number): string;
36
+ }
@@ -0,0 +1,2 @@
1
+ export { default as BinaryMapReader } from './BinaryMapReader';
2
+ export type { MudletMap, MudletArea, MudletRoom, MudletColor, MudletLabel } from 'mudlet-map-binary-reader';
@@ -0,0 +1,34 @@
1
+ import { t as e } from "./MapReader-mU_4JWv_.js";
2
+ import { readMapFromBuffer as t, readerExport as n } from "mudlet-map-binary-reader";
3
+ //#region src/binary/BinaryMapReader.ts
4
+ var r = class r {
5
+ constructor(t) {
6
+ let { mapData: r, colors: i } = n(t);
7
+ this.reader = new e(r, i);
8
+ }
9
+ static fromBuffer(e) {
10
+ return new r(t(e));
11
+ }
12
+ getArea(e) {
13
+ return this.reader.getArea(e);
14
+ }
15
+ getAreas() {
16
+ return this.reader.getAreas();
17
+ }
18
+ getRooms() {
19
+ return this.reader.getRooms();
20
+ }
21
+ getRoom(e) {
22
+ return this.reader.getRoom(e);
23
+ }
24
+ getColorValue(e) {
25
+ return this.reader.getColorValue(e);
26
+ }
27
+ getSymbolColor(e, t) {
28
+ return this.reader.getSymbolColor(e, t);
29
+ }
30
+ };
31
+ //#endregion
32
+ export { r as BinaryMapReader };
33
+
34
+ //# sourceMappingURL=binary.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.mjs","names":[],"sources":["../src/binary/BinaryMapReader.ts"],"sourcesContent":["import {\n type MudletMap,\n readerExport,\n readMapFromBuffer,\n} from \"mudlet-map-binary-reader\";\nimport MapReader, {type IMapReader} from \"../reader/MapReader\";\nimport type {IArea} from \"../reader/Area\";\n\n/**\n * {@link IMapReader} implementation backed by a parsed Mudlet binary map.\n *\n * Convenience wrapper around the existing {@link MapReader} that converts a\n * {@link MudletMap} (the in-memory binary model from\n * `mudlet-map-binary-reader`) into the renderer's `{mapData, colors}` shape\n * via `readerExport()`, then forwards every `IMapReader` call to the wrapped\n * reader.\n *\n * Useful for downstream apps (the upstream Mudix client is one) that already\n * own binary `.dat` bytes and want a single object they can hand to\n * {@link MapRenderer} without staging a separate JSON export step.\n *\n * `mudlet-map-binary-reader` is a `peerDependency`; consumers who do not use\n * binary maps never pay the bundle cost.\n */\nexport default class BinaryMapReader implements IMapReader {\n private readonly reader: MapReader;\n\n /** Build directly from a parsed {@link MudletMap}. */\n constructor(model: MudletMap) {\n const {mapData, colors} = readerExport(model);\n // RendererRoom (binary-reader output) and MapData.Room (renderer\n // input) overlap structurally — RendererRoom is missing only\n // `areaId`, which the renderer never reads from rooms (only from\n // the area). Cast through `unknown` to bridge the nominal gap.\n this.reader = new MapReader(mapData as unknown as MapData.Map, colors);\n }\n\n /**\n * Parse the given binary map buffer and construct a reader from it.\n * In Node, pass `fs.readFileSync(path)`; in the browser, construct a\n * `Buffer` from an `ArrayBuffer` (e.g. via the `buffer` polyfill).\n */\n static fromBuffer(buf: Parameters<typeof readMapFromBuffer>[0]): BinaryMapReader {\n return new BinaryMapReader(readMapFromBuffer(buf));\n }\n\n // --- IMapReader forwarding ---\n\n getArea(areaId: number): IArea {\n return this.reader.getArea(areaId);\n }\n\n getAreas(): IArea[] {\n return this.reader.getAreas();\n }\n\n getRooms(): MapData.Room[] {\n return this.reader.getRooms();\n }\n\n getRoom(roomId: number): MapData.Room {\n return this.reader.getRoom(roomId);\n }\n\n getColorValue(envId: number): string {\n return this.reader.getColorValue(envId);\n }\n\n getSymbolColor(envId: number, opacity?: number): string {\n return this.reader.getSymbolColor(envId, opacity);\n }\n}\n"],"mappings":";;;AAwBA,IAAqB,IAArB,MAAqB,EAAsC;CAIvD,YAAY,GAAkB;EAC1B,IAAM,EAAC,YAAS,cAAU,EAAa,EAAM;AAK7C,OAAK,SAAS,IAAI,EAAU,GAAmC,EAAO;;CAQ1E,OAAO,WAAW,GAA+D;AAC7E,SAAO,IAAI,EAAgB,EAAkB,EAAI,CAAC;;CAKtD,QAAQ,GAAuB;AAC3B,SAAO,KAAK,OAAO,QAAQ,EAAO;;CAGtC,WAAoB;AAChB,SAAO,KAAK,OAAO,UAAU;;CAGjC,WAA2B;AACvB,SAAO,KAAK,OAAO,UAAU;;CAGjC,QAAQ,GAA8B;AAClC,SAAO,KAAK,OAAO,QAAQ,EAAO;;CAGtC,cAAc,GAAuB;AACjC,SAAO,KAAK,OAAO,cAAc,EAAM;;CAG3C,eAAe,GAAe,GAA0B;AACpD,SAAO,KAAK,OAAO,eAAe,GAAO,EAAQ"}
@@ -0,0 +1,118 @@
1
+ import { ViewportBounds } from '../types/Settings';
2
+ import { TypedEventEmitter } from '../TypedEventEmitter';
3
+ /** Pixels-per-world-unit at zoom = 1. Multiply by `Camera.zoom` for actual scale. */
4
+ export declare const BASE_SCALE = 75;
5
+ /** Events fired by {@link Camera}. */
6
+ export type CameraEventMap = {
7
+ /** Any state change: zoom, pan, size, animation tick. */
8
+ change: void;
9
+ };
10
+ /**
11
+ * Engine-agnostic camera — owns transform state, drag, and animation.
12
+ *
13
+ * Subscribers ({@link KonvaRenderer}, {@link CullingManager}, {@link HitTester},
14
+ * scene overlays) listen to the `change` event to react to view updates.
15
+ *
16
+ * No Konva, no DOM. Only dependency is requestAnimationFrame (with a
17
+ * setTimeout fallback for Node.js).
18
+ */
19
+ export declare class Camera extends TypedEventEmitter<CameraEventMap> {
20
+ zoom: number;
21
+ minZoom: number;
22
+ position: {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ width: number;
27
+ height: number;
28
+ /** When true, resizing re-centers on the last panToMapPoint target. */
29
+ centerOnResize: boolean;
30
+ private dragging;
31
+ private dragStart;
32
+ private positionAtDragStart;
33
+ private animationId?;
34
+ private batchDepth;
35
+ private batchDirty;
36
+ constructor(width: number, height: number);
37
+ getScale(): number;
38
+ setZoom(zoom: number): boolean;
39
+ /** Zoom keeping the center of the viewport fixed. */
40
+ zoomToCenter(zoom: number): boolean;
41
+ /** Zoom keeping a specific screen point fixed (for mouse wheel zoom). */
42
+ zoomToPoint(zoom: number, screenX: number, screenY: number): boolean;
43
+ /** Bounds of the visible area in map space. */
44
+ getViewportBounds(): ViewportBounds;
45
+ /**
46
+ * Map-space bounds to use for culling. When `cullingBounds` is a
47
+ * screen-pixel sub-rect it is converted to map space via the current
48
+ * camera transform; otherwise the full viewport is returned.
49
+ */
50
+ getCullingViewport(cullingBounds?: {
51
+ x: number;
52
+ y: number;
53
+ width: number;
54
+ height: number;
55
+ } | null): ViewportBounds;
56
+ /**
57
+ * Create a Camera whose full viewport covers exactly the given world-space bounds.
58
+ * Used by headless exporters that need a Camera but have no real display.
59
+ */
60
+ static forMapBounds(minX: number, maxX: number, minY: number, maxY: number): Camera;
61
+ /**
62
+ * Create a Camera from an explicit render-camera transform (scale + offset).
63
+ * Used by {@link CanvasExporter} to derive culling bounds from the already-
64
+ * computed fitted transform without re-doing the letterbox math.
65
+ */
66
+ static forRenderCamera(width: number, height: number, scale: number, offsetX: number, offsetY: number): Camera;
67
+ /** Convert client/screen coordinates to map coordinates. */
68
+ clientToMapPoint(clientX: number, clientY: number, containerOffset?: {
69
+ left: number;
70
+ top: number;
71
+ }): {
72
+ x: number;
73
+ y: number;
74
+ } | null;
75
+ /** Center on a map coordinate, instantly. */
76
+ panToMapPoint(x: number, y: number): void;
77
+ /** Center on a map coordinate, with optional animation. */
78
+ panToMapPointAnimated(x: number, y: number, instant: boolean): void;
79
+ /**
80
+ * Compute the zoom level that would fit the given map bounds in the current
81
+ * viewport (with the same padding/insets as {@link fitToMapBounds}).
82
+ */
83
+ computeFitZoom(minX: number, maxX: number, minY: number, maxY: number, insets?: {
84
+ top?: number;
85
+ right?: number;
86
+ bottom?: number;
87
+ left?: number;
88
+ }): number;
89
+ /**
90
+ * Fit the camera to show the given map bounds with padding.
91
+ * Optional `insets` (screen pixels) reserve space at each edge.
92
+ */
93
+ fitToMapBounds(minX: number, maxX: number, minY: number, maxY: number, insets?: {
94
+ top?: number;
95
+ right?: number;
96
+ bottom?: number;
97
+ left?: number;
98
+ }): void;
99
+ setSize(width: number, height: number): void;
100
+ startDrag(screenX: number, screenY: number): void;
101
+ updateDrag(screenX: number, screenY: number): void;
102
+ endDrag(): void;
103
+ isDragging(): boolean;
104
+ private animate;
105
+ cancelAnimation(): void;
106
+ isAnimating(): boolean;
107
+ /**
108
+ * Run a function that performs multiple camera mutations and emit only one
109
+ * `change` event at the end (if anything actually mutated). Use this when a
110
+ * single logical operation needs to touch more than one camera field —
111
+ * resize-then-recenter, for example — so subscribers never observe a
112
+ * transient inconsistent state (new size with stale position).
113
+ *
114
+ * Nested batches are supported: only the outermost batch emits.
115
+ */
116
+ batch<T>(fn: () => T): T;
117
+ private notify;
118
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Forward / inverse 2D coordinate transform. Used by camera-aware code that
3
+ * needs to translate between world space (the map's flat XY) and scene space
4
+ * (whatever the active style projects into — e.g. an isometric diamond).
5
+ *
6
+ * `IDENTITY_TRANSFORM` returns the input unchanged; flat styles (Parchment,
7
+ * Sketchy, plain identity) use it for both the forward and inverse direction.
8
+ */
9
+ export type CoordFn = (x: number, y: number) => {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ export declare const IDENTITY_TRANSFORM: CoordFn;
@@ -0,0 +1,25 @@
1
+ export type PlanarDirection = "north" | "south" | "east" | "west" | "northeast" | "northwest" | "southeast" | "southwest";
2
+ export declare const planarDirections: PlanarDirection[];
3
+ export declare const oppositeDirections: Record<PlanarDirection, PlanarDirection>;
4
+ export declare function movePoint(x: number, y: number, direction?: MapData.direction, distance?: number): {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ /**
9
+ * Calculate the edge point of a rounded rectangle for a given direction.
10
+ * Cardinal directions use the flat edge (same as rectangle).
11
+ * Diagonal directions intersect the corner arc.
12
+ */
13
+ export declare function movePointRoundedRect(x: number, y: number, direction?: MapData.direction, distance?: number, cornerRadius?: number): {
14
+ x: number;
15
+ y: number;
16
+ };
17
+ /**
18
+ * Calculate the edge point of a circle for a given direction
19
+ * For circles, we need to calculate the exact point on the circle's circumference
20
+ * based on the angle to the direction
21
+ */
22
+ export declare function movePointCircle(x: number, y: number, direction?: MapData.direction, radius?: number): {
23
+ x: number;
24
+ y: number;
25
+ };
@@ -0,0 +1,104 @@
1
+ import { LayerId } from '../scene/Shape';
2
+ export interface RectCommand {
3
+ type: "rect";
4
+ x: number;
5
+ y: number;
6
+ w: number;
7
+ h: number;
8
+ fill?: string;
9
+ stroke?: string;
10
+ /** Stroke width in render units. */
11
+ sw: number;
12
+ /** Corner radius in render units. */
13
+ cr: number;
14
+ dash?: number[];
15
+ }
16
+ export interface CircleCommand {
17
+ type: "circle";
18
+ cx: number;
19
+ cy: number;
20
+ r: number;
21
+ fill?: string;
22
+ stroke?: string;
23
+ sw: number;
24
+ dash?: number[];
25
+ }
26
+ export interface LineCommand {
27
+ type: "line";
28
+ /** Flat list of [x0, y0, x1, y1, …] in render space. */
29
+ points: number[];
30
+ stroke?: string;
31
+ sw: number;
32
+ dash?: number[];
33
+ lineCap?: "butt" | "round" | "square";
34
+ lineJoin?: "miter" | "round" | "bevel";
35
+ /** 0..1 multiplier. */
36
+ alpha?: number;
37
+ }
38
+ export interface PolygonCommand {
39
+ type: "polygon";
40
+ vertices: number[];
41
+ fill?: string;
42
+ stroke?: string;
43
+ sw: number;
44
+ }
45
+ export interface TextCommand {
46
+ type: "text";
47
+ x: number;
48
+ y: number;
49
+ text: string;
50
+ fontSize: number;
51
+ fontFamily: string;
52
+ fontStyle: string;
53
+ fill: string;
54
+ stroke?: string;
55
+ /** Stroke width in render units (0 = no stroke). */
56
+ sw: number;
57
+ align: "left" | "center" | "right";
58
+ vAlign: "top" | "middle" | "bottom";
59
+ w: number;
60
+ h: number;
61
+ baselineRatio?: number;
62
+ konvaCorrectionRatio?: number;
63
+ transform?: [number, number, number, number, number, number];
64
+ }
65
+ export interface ImageCommand {
66
+ type: "image";
67
+ x: number;
68
+ y: number;
69
+ w: number;
70
+ h: number;
71
+ src: string;
72
+ transform?: [number, number, number, number, number, number];
73
+ }
74
+ /** Push an affine transform [a, b, c, d, e, f] onto the renderer's stack. */
75
+ export interface PushTransformCommand {
76
+ type: "pushTransform";
77
+ matrix: [number, number, number, number, number, number];
78
+ }
79
+ /** Pop the most recent transform. */
80
+ export interface PopTransformCommand {
81
+ type: "popTransform";
82
+ }
83
+ /** Push a clip rect; subsequent draws are clipped until matching pop. */
84
+ export interface PushClipCommand {
85
+ type: "pushClip";
86
+ x: number;
87
+ y: number;
88
+ w: number;
89
+ h: number;
90
+ }
91
+ export interface PopClipCommand {
92
+ type: "popClip";
93
+ }
94
+ export type PrimitiveDrawCommand = RectCommand | CircleCommand | LineCommand | PolygonCommand | TextCommand | ImageCommand;
95
+ export type StackDrawCommand = PushTransformCommand | PopTransformCommand | PushClipCommand | PopClipCommand;
96
+ export type DrawCommand = PrimitiveDrawCommand | StackDrawCommand;
97
+ /**
98
+ * A bundle of commands targeting one logical layer. Renderers iterate layers
99
+ * in z-order and flush commands per layer.
100
+ */
101
+ export interface DrawCommandBatch {
102
+ layer: LayerId;
103
+ commands: DrawCommand[];
104
+ }
@@ -0,0 +1,19 @@
1
+ import { DrawCommandBatch } from './DrawCommand';
2
+ import { Shape } from '../scene/Shape';
3
+ /** Camera state needed to project world coordinates into render space. */
4
+ export interface CameraTransform {
5
+ /** Pixels per world unit. */
6
+ scale: number;
7
+ /** Render-space origin in pixels. */
8
+ offsetX: number;
9
+ offsetY: number;
10
+ }
11
+ /**
12
+ * Build per-layer {@link DrawCommandBatch}es from a list of world-space shapes
13
+ * and an active camera transform.
14
+ *
15
+ * Layer order in the result follows first-appearance order; renderers iterate
16
+ * the array as-is (z-order is the caller's responsibility — typically scene
17
+ * layout uses the LayerId taxonomy to pre-sort).
18
+ */
19
+ export declare function buildDrawCommands(shapes: Shape[], camera: CameraTransform): DrawCommandBatch[];