mudlet-map-renderer 1.0.0 → 1.1.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 +520 -0
- package/dist/AreaMapRenderer.d.ts +125 -0
- package/dist/CullingManager.d.ts +15 -0
- package/dist/ExitRenderer.d.ts +109 -0
- package/dist/InteractionHandler.d.ts +47 -0
- package/dist/MapGraph.d.ts +28 -0
- package/dist/MapReader-mU_4JWv_.js +224 -0
- package/dist/MapReader-mU_4JWv_.js.map +1 -0
- package/dist/MapState.d.ts +110 -0
- package/dist/PathData.d.ts +18 -0
- package/dist/PathFinder.d.ts +12 -0
- package/dist/ScenePipeline.d.ts +226 -0
- package/dist/SvgTypes.d.ts +21 -0
- package/dist/TypedEventEmitter.d.ts +17 -0
- package/dist/binary/BinaryMapReader.d.ts +36 -0
- package/dist/binary/index.d.ts +2 -0
- package/dist/binary.mjs +34 -0
- package/dist/binary.mjs.map +1 -0
- package/dist/camera/Camera.d.ts +106 -0
- package/dist/coord/CoordFn.d.ts +13 -0
- package/dist/directions.d.ts +25 -0
- package/dist/draw/DrawCommand.d.ts +104 -0
- package/dist/draw/DrawCommandBuilder.d.ts +19 -0
- package/dist/export/CanvasExporter.d.ts +71 -0
- package/dist/export/Exporter.d.ts +58 -0
- package/dist/export/PngExporter.d.ts +23 -0
- package/dist/export/SvgExporter.d.ts +19 -0
- package/dist/export/canvasToBytes.d.ts +19 -0
- package/dist/export/clipSceneToViewport.d.ts +48 -0
- package/dist/export/flushSceneShapes.d.ts +21 -0
- package/dist/export/sceneBounds.d.ts +24 -0
- package/dist/hit/HitTester.d.ts +101 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.mjs +6656 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lens/ExplorationLens.d.ts +29 -0
- package/dist/lens/RoomLens.d.ts +47 -0
- package/dist/lens/composeLenses.d.ts +31 -0
- package/dist/lens/index.d.ts +5 -0
- package/dist/overlay/AmbientLightOverlay.d.ts +32 -0
- package/dist/overlay/LiveEffect.d.ts +33 -0
- package/dist/overlay/SceneOverlay.d.ts +68 -0
- package/dist/reader/Area.d.ts +63 -0
- package/dist/reader/Exit.d.ts +15 -0
- package/dist/reader/MapReader.d.ts +34 -0
- package/dist/reader/Plane.d.ts +33 -0
- package/dist/render/CanvasRenderer.d.ts +17 -0
- package/dist/render/RecordingLayer.d.ts +158 -0
- package/dist/render/SvgRenderer.d.ts +7 -0
- package/dist/render/shapeToRecording.d.ts +3 -0
- package/dist/rendering/KonvaRenderBackend.d.ts +122 -0
- package/dist/rendering/MapRenderer.d.ts +213 -0
- package/dist/rendering/SceneManager.d.ts +54 -0
- package/dist/scene/AmbientLightStyle.d.ts +29 -0
- package/dist/scene/GridStyle.d.ts +21 -0
- package/dist/scene/InnerExitStyle.d.ts +24 -0
- package/dist/scene/OverlayStyle.d.ts +47 -0
- package/dist/scene/RoomStyle.d.ts +32 -0
- package/dist/scene/Shape.d.ts +151 -0
- package/dist/scene/SpecialExitStyle.d.ts +37 -0
- package/dist/scene/StubStyle.d.ts +15 -0
- package/dist/scene/elements/ExitLayout.d.ts +22 -0
- package/dist/scene/elements/GridLayout.d.ts +24 -0
- package/dist/scene/elements/LabelLayout.d.ts +11 -0
- package/dist/scene/elements/OverlayLayout.d.ts +14 -0
- package/dist/scene/elements/RoomLayout.d.ts +19 -0
- package/dist/scene/elements/SpecialExitLayout.d.ts +19 -0
- package/dist/scene/elements/StubLayout.d.ts +19 -0
- package/dist/style/Style.d.ts +60 -0
- package/dist/style/applyStyle.d.ts +3 -0
- package/dist/style/index.d.ts +21 -0
- package/dist/style/shape/BlueprintStyle.d.ts +11 -0
- package/dist/style/shape/ConstructionStyle.d.ts +17 -0
- package/dist/style/shape/IsometricStyle.d.ts +32 -0
- package/dist/style/shape/NeonStyle.d.ts +17 -0
- package/dist/style/shape/ParchmentStyle.d.ts +13 -0
- package/dist/style/shape/SciFiStyle.d.ts +16 -0
- package/dist/style/shape/SketchyStyle.d.ts +22 -0
- package/dist/style/shape/index.d.ts +25 -0
- package/dist/style/shape/paintMap.d.ts +25 -0
- package/dist/style/shape/wobble.d.ts +24 -0
- package/{src/types/MapData.ts → dist/types/MapData.d.ts} +70 -90
- package/dist/types/Settings.d.ts +206 -0
- package/dist/utils/color.d.ts +12 -0
- package/dist/utils/textMeasure.d.ts +38 -0
- package/package.json +67 -37
- package/demo/colors.json +0 -1
- package/demo/index.html +0 -102
- package/demo/main.ts +0 -389
- package/demo/mapExport.json +0 -1
- package/demo/tsconfig.json +0 -11
- package/src/ExitRenderer.ts +0 -275
- package/src/PathFinder.ts +0 -93
- package/src/PathRenderer.ts +0 -129
- package/src/Renderer.ts +0 -374
- package/src/directions.ts +0 -66
- package/src/index.ts +0 -4
- package/src/reader/Area.ts +0 -96
- package/src/reader/Exit.ts +0 -36
- package/src/reader/ExplorationArea.ts +0 -132
- package/src/reader/MapReader.ts +0 -123
- package/src/reader/Plane.ts +0 -42
- package/tsconfig.json +0 -17
- package/vercel.json +0 -5
- package/vite.config.ts +0 -29
- package/vite.demo.config.ts +0 -15
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RoomLens } from './RoomLens';
|
|
2
|
+
/**
|
|
3
|
+
* Fog-of-war lens: rooms render only when their id is in the visited set.
|
|
4
|
+
*
|
|
5
|
+
* Default exit treatment is left to {@link RoomLens}'s built-in derivation
|
|
6
|
+
* (both visible → full, one visible → stub, neither → hidden), which produces
|
|
7
|
+
* the "explored frontier" look without any extra wiring.
|
|
8
|
+
*
|
|
9
|
+
* Mutations bump {@link getVersion} so a composing renderer can detect the
|
|
10
|
+
* change; the renderer still needs an explicit `refresh()` after mutation —
|
|
11
|
+
* the lens doesn't emit events.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ExplorationLens implements RoomLens {
|
|
14
|
+
private readonly visited;
|
|
15
|
+
private version;
|
|
16
|
+
constructor(visited?: Iterable<number>);
|
|
17
|
+
isVisible(room: MapData.Room): boolean;
|
|
18
|
+
getVersion(): number;
|
|
19
|
+
hasVisited(roomId: number): boolean;
|
|
20
|
+
getVisitedRoomIds(): number[];
|
|
21
|
+
getVisitedCount(): number;
|
|
22
|
+
/** Returns true if the room was newly added. */
|
|
23
|
+
addVisited(roomId: number): boolean;
|
|
24
|
+
/** Returns the number of newly added rooms. */
|
|
25
|
+
addVisitedAll(roomIds: Iterable<number>): number;
|
|
26
|
+
/** Replace the visited set wholesale. */
|
|
27
|
+
setVisited(roomIds: Iterable<number>): void;
|
|
28
|
+
clear(): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { default as IExit } from '../reader/Exit';
|
|
2
|
+
/**
|
|
3
|
+
* How the renderer should treat an exit whose endpoints are not both visible.
|
|
4
|
+
*
|
|
5
|
+
* - `"full"` — draw the exit normally (both endpoints are visible, or the
|
|
6
|
+
* lens overrides the default and wants the full line anyway).
|
|
7
|
+
* - `"stub"` — draw only a short stub leaving the visible endpoint; the
|
|
8
|
+
* far end isn't shown. This is the "explored frontier" look.
|
|
9
|
+
* - `"hidden"` — don't draw the exit at all.
|
|
10
|
+
*
|
|
11
|
+
* Cross-area exits (rooms in different `area` ids) are an orthogonal concept
|
|
12
|
+
* decided by raw room data, not by the lens. A lens that returns `"full"` for
|
|
13
|
+
* a cross-area exit still gets the cross-area arrow treatment.
|
|
14
|
+
*/
|
|
15
|
+
export type ExitTreatment = "full" | "stub" | "hidden";
|
|
16
|
+
/**
|
|
17
|
+
* Visibility filter applied during scene build.
|
|
18
|
+
*
|
|
19
|
+
* `IArea` / `IPlane` / `IMapReader` are pure data — they return every room and
|
|
20
|
+
* every link exit the underlying map defines. The lens decides which of those
|
|
21
|
+
* actually paint, and (optionally) how partially-visible exits should be
|
|
22
|
+
* stubbed or hidden. Multiple concerns (exploration, guild scope, quest
|
|
23
|
+
* overlay, …) compose through {@link composeLenses}.
|
|
24
|
+
*/
|
|
25
|
+
export interface RoomLens {
|
|
26
|
+
isVisible(room: MapData.Room): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Decide how an exit between `a` and `b` should be drawn.
|
|
29
|
+
*
|
|
30
|
+
* Optional — when omitted, treatment is derived from endpoint visibility:
|
|
31
|
+
* both visible → `"full"`, one visible → `"stub"`, neither → `"hidden"`.
|
|
32
|
+
*/
|
|
33
|
+
getExitTreatment?(exit: IExit, a: MapData.Room, b: MapData.Room): ExitTreatment;
|
|
34
|
+
/**
|
|
35
|
+
* Monotonically increasing version. The renderer caches the value from the
|
|
36
|
+
* last build and rebuilds when it changes. Mutations on a stateful lens
|
|
37
|
+
* (e.g. {@link ExplorationLens.addVisited}) bump this; callers that mutate
|
|
38
|
+
* the lens still call `renderer.refresh()` explicitly.
|
|
39
|
+
*/
|
|
40
|
+
getVersion(): number;
|
|
41
|
+
}
|
|
42
|
+
export declare const ALL_VISIBLE: RoomLens;
|
|
43
|
+
/**
|
|
44
|
+
* Default treatment when no lens supplies `getExitTreatment`: derive purely
|
|
45
|
+
* from endpoint visibility.
|
|
46
|
+
*/
|
|
47
|
+
export declare function defaultExitTreatment(lens: RoomLens, _exit: IExit, a: MapData.Room, b: MapData.Room): ExitTreatment;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RoomLens } from './RoomLens';
|
|
2
|
+
/**
|
|
3
|
+
* How a composite lens reconciles disagreeing children when both expose
|
|
4
|
+
* `getExitTreatment`.
|
|
5
|
+
*
|
|
6
|
+
* - `"most-restrictive"` (default): `hidden` > `stub` > `full`. A single
|
|
7
|
+
* child that says hide wins. Safe default for stacked visibility filters.
|
|
8
|
+
* - `"least-restrictive"`: `full` > `stub` > `hidden`. Useful when lenses are
|
|
9
|
+
* additive scopes ("show guild rooms OR quest rooms").
|
|
10
|
+
* - `"first"`: the first child whose `getExitTreatment` returns non-undefined
|
|
11
|
+
* decides. Lets the caller pick a dominant lens by ordering.
|
|
12
|
+
*/
|
|
13
|
+
export type ExitConflictStrategy = "most-restrictive" | "least-restrictive" | "first";
|
|
14
|
+
export type ComposeOptions = {
|
|
15
|
+
/** Defaults to `"most-restrictive"`. */
|
|
16
|
+
exitStrategy?: ExitConflictStrategy;
|
|
17
|
+
/**
|
|
18
|
+
* AND (visibility must hold in every lens) vs OR (any lens may grant
|
|
19
|
+
* visibility). Defaults to `"and"` — restrictive intersection.
|
|
20
|
+
*/
|
|
21
|
+
visibility?: "and" | "or";
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Combine multiple lenses into one. Visibility uses AND by default (a room
|
|
25
|
+
* must pass every lens to render); exit treatment uses most-restrictive when
|
|
26
|
+
* children disagree. Both behaviours are configurable via {@link ComposeOptions}.
|
|
27
|
+
*
|
|
28
|
+
* Composing zero lenses returns a no-op equivalent to `ALL_VISIBLE`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function composeLenses(...lenses: RoomLens[]): RoomLens;
|
|
31
|
+
export declare function composeLenses(options: ComposeOptions, ...lenses: RoomLens[]): RoomLens;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { RoomLens, ExitTreatment } from './RoomLens';
|
|
2
|
+
export { ALL_VISIBLE, defaultExitTreatment } from './RoomLens';
|
|
3
|
+
export { composeLenses } from './composeLenses';
|
|
4
|
+
export type { ComposeOptions, ExitConflictStrategy } from './composeLenses';
|
|
5
|
+
export { ExplorationLens } from './ExplorationLens';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MapState } from '../MapState';
|
|
2
|
+
import { ViewportBounds } from '../types/Settings';
|
|
3
|
+
import { AmbientLightParams } from '../scene/AmbientLightStyle';
|
|
4
|
+
import { Shape } from '../scene/Shape';
|
|
5
|
+
import { SceneOverlay, SceneOverlayContext } from './SceneOverlay';
|
|
6
|
+
export type AmbientLightOptions = Partial<AmbientLightParams>;
|
|
7
|
+
/**
|
|
8
|
+
* Vignette centered on the player room. Re-renders on position changes and
|
|
9
|
+
* viewport changes (pan/zoom/resize). Registering the overlay turns the effect
|
|
10
|
+
* on; removing it turns it off — there is no global settings flag.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const ambient = new AmbientLightOverlay({ color: '#ffcc44', radius: 12 });
|
|
14
|
+
* renderer.addSceneOverlay('ambient-light', ambient);
|
|
15
|
+
* // later:
|
|
16
|
+
* ambient.setOptions({ intensity: 0.9 });
|
|
17
|
+
* renderer.removeSceneOverlay('ambient-light');
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class AmbientLightOverlay implements SceneOverlay {
|
|
21
|
+
private params;
|
|
22
|
+
private ctx?;
|
|
23
|
+
private viewportUnsub?;
|
|
24
|
+
private readonly onPosition;
|
|
25
|
+
constructor(options?: AmbientLightOptions);
|
|
26
|
+
/** Update tunables at runtime. Triggers a re-render. */
|
|
27
|
+
setOptions(options: AmbientLightOptions): void;
|
|
28
|
+
getOptions(): AmbientLightParams;
|
|
29
|
+
attach(ctx: SceneOverlayContext): void;
|
|
30
|
+
detach(): void;
|
|
31
|
+
render(state: MapState, bounds: ViewportBounds): Shape | void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { default as Konva } from 'konva';
|
|
2
|
+
import { ViewportBounds } from '../types/Settings';
|
|
3
|
+
/** Map-space → render-space coordinate transform. */
|
|
4
|
+
export type CoordinateTransform = (x: number, y: number) => {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Interactive-only animated effect. A {@link LiveEffect} receives a live Konva
|
|
10
|
+
* layer and viewport updates so it can react to pan/zoom and run its own
|
|
11
|
+
* animation loop.
|
|
12
|
+
*
|
|
13
|
+
* Exporters (SVG, PNG, PDF, …) skip `LiveEffect`s by design — use
|
|
14
|
+
* `SceneOverlay` when you need an overlay to appear in exports.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* class PulseEffect implements LiveEffect {
|
|
18
|
+
* private shape?: Konva.Shape;
|
|
19
|
+
* attach(layer: Konva.Layer) {
|
|
20
|
+
* this.shape = new Konva.Shape({ sceneFunc: (ctx) => { ... } });
|
|
21
|
+
* layer.add(this.shape);
|
|
22
|
+
* }
|
|
23
|
+
* updateViewport(bounds, scale) { ... }
|
|
24
|
+
* destroy() { this.shape?.destroy(); }
|
|
25
|
+
* }
|
|
26
|
+
* renderer.konvaBackend?.addLiveEffect('pulse', new PulseEffect());
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface LiveEffect {
|
|
30
|
+
attach(layer: Konva.Layer): void;
|
|
31
|
+
updateViewport(bounds: ViewportBounds, scale: number, coordinateTransform: CoordinateTransform): void;
|
|
32
|
+
destroy(): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MapState } from '../MapState';
|
|
2
|
+
import { ViewportBounds } from '../types/Settings';
|
|
3
|
+
import { Shape } from '../scene/Shape';
|
|
4
|
+
/**
|
|
5
|
+
* Context handed to a {@link SceneOverlay} when it is registered. Gives the
|
|
6
|
+
* overlay access to {@link MapState} events, viewport changes, and a way to
|
|
7
|
+
* request its own re-render.
|
|
8
|
+
*/
|
|
9
|
+
export interface SceneOverlayContext {
|
|
10
|
+
readonly state: MapState;
|
|
11
|
+
/**
|
|
12
|
+
* Subscribe to viewport changes (pan, zoom, resize). Returns an unsubscribe
|
|
13
|
+
* function — call it from {@link SceneOverlay.detach} to avoid leaks.
|
|
14
|
+
*/
|
|
15
|
+
onViewportChange(cb: () => void): () => void;
|
|
16
|
+
/** Request a re-render of this overlay only. Cheap — no full scene rebuild. */
|
|
17
|
+
invalidate(): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Target-agnostic overlay. A {@link SceneOverlay} contributes static geometry
|
|
21
|
+
* to the scene by emitting one or more {@link Shape}s, so it renders in every
|
|
22
|
+
* output path: interactive canvas, SVG export, PNG export, and any future
|
|
23
|
+
* {@link Exporter}.
|
|
24
|
+
*
|
|
25
|
+
* Overlays may opt into reactivity via {@link attach}: subscribe to MapState or
|
|
26
|
+
* viewport events, then call `ctx.invalidate()` to re-render. Exporters skip
|
|
27
|
+
* `attach`/`detach` — they just call {@link render} once.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* class BadgeOverlay implements SceneOverlay {
|
|
31
|
+
* render(state: MapState, bounds: ViewportBounds): Shape {
|
|
32
|
+
* return {
|
|
33
|
+
* type: 'circle',
|
|
34
|
+
* cx: 5, cy: 5,
|
|
35
|
+
* radius: 0.4,
|
|
36
|
+
* paint: { fill: '#ff0' },
|
|
37
|
+
* layer: 'overlay',
|
|
38
|
+
* };
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* renderer.addSceneOverlay('badge', new BadgeOverlay());
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export interface SceneOverlay {
|
|
46
|
+
/**
|
|
47
|
+
* Optional. Called once when the overlay is registered with an interactive
|
|
48
|
+
* renderer. Subscribe to events here and call `ctx.invalidate()` when the
|
|
49
|
+
* overlay needs to re-render.
|
|
50
|
+
*
|
|
51
|
+
* Not called by exporters — they render statically via {@link render}.
|
|
52
|
+
*/
|
|
53
|
+
attach?(ctx: SceneOverlayContext): void;
|
|
54
|
+
/**
|
|
55
|
+
* Optional. Called when the overlay is removed (or the renderer is
|
|
56
|
+
* destroyed). Unsubscribe from any events registered in {@link attach}.
|
|
57
|
+
*/
|
|
58
|
+
detach?(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Contribute geometry to the scene. Called on register, on invalidate, and
|
|
61
|
+
* by every exporter.
|
|
62
|
+
*
|
|
63
|
+
* @returns one or more world-space {@link Shape}s, or `void` to emit
|
|
64
|
+
* nothing this frame. Shapes carry their own {@link Shape.layer} hint;
|
|
65
|
+
* leaving it unset routes them to the overlay layer.
|
|
66
|
+
*/
|
|
67
|
+
render(state: MapState, bounds: ViewportBounds): Shape | Shape[] | void;
|
|
68
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { default as Plane, IPlane } from './Plane';
|
|
2
|
+
import { default as IExit } from './Exit';
|
|
3
|
+
/**
|
|
4
|
+
* Public, renderer-facing surface of an area. The renderer never inspects
|
|
5
|
+
* private state of {@link Area}; it talks to this interface only. Custom data
|
|
6
|
+
* models (e.g. an app that owns its own room store) can satisfy `IArea` and
|
|
7
|
+
* hand the result to {@link MapRenderer} without subclassing.
|
|
8
|
+
*
|
|
9
|
+
* Mutability lives on the concrete implementation: {@link Area.markDirty} is
|
|
10
|
+
* `protected`, kept off the public interface. Consumers signal "redraw me" by
|
|
11
|
+
* bumping {@link getVersion}; the renderer reads the version to decide
|
|
12
|
+
* whether to rebuild.
|
|
13
|
+
*/
|
|
14
|
+
export interface IArea {
|
|
15
|
+
getAreaName(): string;
|
|
16
|
+
getAreaId(): number;
|
|
17
|
+
/**
|
|
18
|
+
* Monotonically increasing version. The renderer compares the value it
|
|
19
|
+
* cached on the last build against the current value to decide whether
|
|
20
|
+
* the area needs a rebuild.
|
|
21
|
+
*/
|
|
22
|
+
getVersion(): number;
|
|
23
|
+
getPlane(zIndex: number): IPlane;
|
|
24
|
+
getPlanes(): IPlane[];
|
|
25
|
+
getZLevels(): number[];
|
|
26
|
+
getRooms(): MapData.Room[];
|
|
27
|
+
getFullBounds(): {
|
|
28
|
+
minX: number;
|
|
29
|
+
maxX: number;
|
|
30
|
+
minY: number;
|
|
31
|
+
maxY: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Inter-room exits drawn on the given z-level. Each exit is bidirectional
|
|
35
|
+
* with optional one-way fallback; see {@link IExit}.
|
|
36
|
+
*/
|
|
37
|
+
getLinkExits(zIndex: number): IExit[];
|
|
38
|
+
}
|
|
39
|
+
export default class Area implements IArea {
|
|
40
|
+
private readonly planes;
|
|
41
|
+
private readonly area;
|
|
42
|
+
private readonly exits;
|
|
43
|
+
private version;
|
|
44
|
+
constructor(area: MapData.Area);
|
|
45
|
+
getAreaName(): string;
|
|
46
|
+
getAreaId(): number;
|
|
47
|
+
getVersion(): number;
|
|
48
|
+
protected markDirty(): void;
|
|
49
|
+
getPlane(zIndex: number): Plane;
|
|
50
|
+
getPlanes(): Plane[];
|
|
51
|
+
getZLevels(): number[];
|
|
52
|
+
getRooms(): MapData.Room[];
|
|
53
|
+
getFullBounds(): {
|
|
54
|
+
minX: number;
|
|
55
|
+
maxX: number;
|
|
56
|
+
minY: number;
|
|
57
|
+
maxY: number;
|
|
58
|
+
};
|
|
59
|
+
getLinkExits(zIndex: number): IExit[];
|
|
60
|
+
private createPlanes;
|
|
61
|
+
private static readonly oppositeDir;
|
|
62
|
+
private createExits;
|
|
63
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Kind = "exit" | "specialExit";
|
|
2
|
+
export default interface IExit {
|
|
3
|
+
a: number;
|
|
4
|
+
b: number;
|
|
5
|
+
aDir?: MapData.direction;
|
|
6
|
+
bDir?: MapData.direction;
|
|
7
|
+
kind?: Kind;
|
|
8
|
+
zIndex: number[];
|
|
9
|
+
}
|
|
10
|
+
export type { IExit };
|
|
11
|
+
/** @deprecated Use {@link IExit}. Retained as a structural alias for backwards compatibility. */
|
|
12
|
+
export type Exit = IExit;
|
|
13
|
+
export declare const regularExits: MapData.direction[];
|
|
14
|
+
export declare const shortTolong: Record<string, MapData.direction>;
|
|
15
|
+
export declare const longToShort: Record<MapData.direction, string>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { default as Area, IArea } from './Area';
|
|
2
|
+
/**
|
|
3
|
+
* Public, renderer-facing surface for map data. Everything the renderer
|
|
4
|
+
* (and other library consumers) call on `MapReader` is on this interface —
|
|
5
|
+
* private state and internal helpers are not.
|
|
6
|
+
*
|
|
7
|
+
* Downstream apps with their own room/area store can implement `IMapReader`
|
|
8
|
+
* directly (no need to subclass {@link MapReader}) and hand the result to
|
|
9
|
+
* {@link MapRenderer}. Visibility filtering (exploration, scope overlays,
|
|
10
|
+
* etc.) lives on the renderer's lens — it is intentionally not on this
|
|
11
|
+
* interface.
|
|
12
|
+
*/
|
|
13
|
+
export interface IMapReader {
|
|
14
|
+
getArea(areaId: number): IArea;
|
|
15
|
+
getAreas(): IArea[];
|
|
16
|
+
getRooms(): MapData.Room[];
|
|
17
|
+
getRoom(roomId: number): MapData.Room;
|
|
18
|
+
/** Returns the env's `rgb(r,g,b)` string, or a default colour if the env id is unknown. */
|
|
19
|
+
getColorValue(envId: number): string;
|
|
20
|
+
/** Returns a contrasting symbol colour for the env, optionally with the given alpha. */
|
|
21
|
+
getSymbolColor(envId: number, opacity?: number): string;
|
|
22
|
+
}
|
|
23
|
+
export default class MapReader implements IMapReader {
|
|
24
|
+
private rooms;
|
|
25
|
+
private areas;
|
|
26
|
+
private colors;
|
|
27
|
+
constructor(map: MapData.Map, envs: MapData.Env[]);
|
|
28
|
+
getArea(areaId: number): Area;
|
|
29
|
+
getAreas(): Area[];
|
|
30
|
+
getRooms(): MapData.Room[];
|
|
31
|
+
getRoom(roomId: number): MapData.Room;
|
|
32
|
+
getColorValue(envId: number): string;
|
|
33
|
+
getSymbolColor(envId: number, opacity?: number): string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public, renderer-facing surface of a z-level slice of an area.
|
|
3
|
+
*
|
|
4
|
+
* The renderer (and other library consumers) only depend on this interface;
|
|
5
|
+
* the concrete {@link Plane} class is one implementation of it. Downstream
|
|
6
|
+
* apps that want to drive the renderer from their own data model can hand it
|
|
7
|
+
* any `IPlane`-shaped object (typically returned from an {@link IArea}).
|
|
8
|
+
*/
|
|
9
|
+
export interface IPlane {
|
|
10
|
+
getRooms(): MapData.Room[];
|
|
11
|
+
getLabels(): MapData.Label[];
|
|
12
|
+
getBounds(): {
|
|
13
|
+
minX: number;
|
|
14
|
+
maxX: number;
|
|
15
|
+
minY: number;
|
|
16
|
+
maxY: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export default class Plane implements IPlane {
|
|
20
|
+
private readonly bounds;
|
|
21
|
+
private readonly rooms;
|
|
22
|
+
private readonly labels;
|
|
23
|
+
constructor(rooms: MapData.Room[], labels: MapData.Label[]);
|
|
24
|
+
getRooms(): MapData.Room[];
|
|
25
|
+
getLabels(): MapData.Label[];
|
|
26
|
+
getBounds(): {
|
|
27
|
+
minX: number;
|
|
28
|
+
maxX: number;
|
|
29
|
+
minY: number;
|
|
30
|
+
maxY: number;
|
|
31
|
+
};
|
|
32
|
+
private createBounds;
|
|
33
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DrawCommandBatch } from '../draw/DrawCommand';
|
|
2
|
+
/**
|
|
3
|
+
* Image loader hook. Canvas2D's `drawImage` needs an `HTMLImageElement` (or
|
|
4
|
+
* compatible). Browsers create one via `new Image()`; Node-canvas provides
|
|
5
|
+
* its own `Image` constructor. The default tries both — callers can override
|
|
6
|
+
* for tests or unusual targets.
|
|
7
|
+
*/
|
|
8
|
+
export type ImageFactory = (src: string) => unknown;
|
|
9
|
+
export interface CanvasRenderOptions {
|
|
10
|
+
imageFactory?: ImageFactory;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Replay every batch onto `ctx`, in order. Each batch's commands are flushed
|
|
14
|
+
* sequentially; transform / clip stacks are independent per batch so a stray
|
|
15
|
+
* push in one layer cannot leak into the next.
|
|
16
|
+
*/
|
|
17
|
+
export declare function renderToCanvas(ctx: CanvasRenderingContext2D, batches: DrawCommandBatch[], options?: CanvasRenderOptions): void;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { default as Konva } from 'konva';
|
|
2
|
+
type RectCommand = {
|
|
3
|
+
type: 'rect';
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
fill?: string;
|
|
9
|
+
stroke?: string;
|
|
10
|
+
sw: number;
|
|
11
|
+
cr: number;
|
|
12
|
+
dash?: number[];
|
|
13
|
+
};
|
|
14
|
+
type CircleCommand = {
|
|
15
|
+
type: 'circle';
|
|
16
|
+
cx: number;
|
|
17
|
+
cy: number;
|
|
18
|
+
r: number;
|
|
19
|
+
fill?: string;
|
|
20
|
+
stroke?: string;
|
|
21
|
+
sw: number;
|
|
22
|
+
dash?: number[];
|
|
23
|
+
};
|
|
24
|
+
type LineCommand = {
|
|
25
|
+
type: 'line';
|
|
26
|
+
points: number[];
|
|
27
|
+
stroke?: string;
|
|
28
|
+
sw: number;
|
|
29
|
+
dash?: number[];
|
|
30
|
+
lineCap?: string;
|
|
31
|
+
lineJoin?: string;
|
|
32
|
+
alpha?: number;
|
|
33
|
+
};
|
|
34
|
+
type PolygonCommand = {
|
|
35
|
+
type: 'polygon';
|
|
36
|
+
vertices: number[];
|
|
37
|
+
fill?: string;
|
|
38
|
+
stroke?: string;
|
|
39
|
+
sw: number;
|
|
40
|
+
};
|
|
41
|
+
type TextCommand = {
|
|
42
|
+
type: 'text';
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
text: string;
|
|
46
|
+
fontSize: number;
|
|
47
|
+
fontFamily: string;
|
|
48
|
+
fontStyle: string;
|
|
49
|
+
fill: string;
|
|
50
|
+
stroke?: string;
|
|
51
|
+
sw: number;
|
|
52
|
+
align: string;
|
|
53
|
+
vAlign: string;
|
|
54
|
+
w: number;
|
|
55
|
+
h: number;
|
|
56
|
+
baselineRatio?: number;
|
|
57
|
+
transform?: [number, number, number, number, number, number];
|
|
58
|
+
};
|
|
59
|
+
type ImageCommand = {
|
|
60
|
+
type: 'image';
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
w: number;
|
|
64
|
+
h: number;
|
|
65
|
+
image: HTMLImageElement | any;
|
|
66
|
+
transform?: [number, number, number, number, number, number];
|
|
67
|
+
};
|
|
68
|
+
export type RecordingDrawCommand = RectCommand | CircleCommand | LineCommand | PolygonCommand | TextCommand | ImageCommand;
|
|
69
|
+
/**
|
|
70
|
+
* One positional group of recorded draw commands. Used as both the unit a
|
|
71
|
+
* shape walker emits and the cull-tracking handle inside
|
|
72
|
+
* {@link DrawCommandLayerNode}. Lazily materializes into a `Konva.Group` /
|
|
73
|
+
* `Konva.Shape` pair when added directly to a Konva layer.
|
|
74
|
+
*/
|
|
75
|
+
export declare class RecordingGroupNode {
|
|
76
|
+
x: number;
|
|
77
|
+
y: number;
|
|
78
|
+
_visible: boolean;
|
|
79
|
+
noScaling: boolean;
|
|
80
|
+
readonly commands: RecordingDrawCommand[];
|
|
81
|
+
/** Lazily created when this group is materialized for a Konva.Layer. */
|
|
82
|
+
_konvaGroup?: Konva.Group;
|
|
83
|
+
constructor(x: number, y: number);
|
|
84
|
+
setVisible(visible: boolean): void;
|
|
85
|
+
isVisible(): boolean;
|
|
86
|
+
destroy(): void;
|
|
87
|
+
setPosition(x: number, y: number): void;
|
|
88
|
+
getPosition(): {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
};
|
|
92
|
+
moveToTop(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Materialize this recording as a Konva.Group + Konva.Shape. Used by
|
|
95
|
+
* {@link MaterializingLayerNode} for layers that want individual nodes
|
|
96
|
+
* (overlay, position) rather than a single bulk replay.
|
|
97
|
+
*/
|
|
98
|
+
materialize(): Konva.Group;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Lightweight record extracted from a {@link RecordingGroupNode} when added
|
|
102
|
+
* to a {@link DrawCommandLayerNode}. Contains only plain data so culling
|
|
103
|
+
* callbacks can toggle visibility without a Konva node reference.
|
|
104
|
+
*/
|
|
105
|
+
export type DrawEntry = {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
noScaling: boolean;
|
|
109
|
+
readonly commands: RecordingDrawCommand[];
|
|
110
|
+
visible: boolean;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* LayerNode backed by a single Konva.Shape whose sceneFunc replays
|
|
114
|
+
* {@link DrawEntry} objects. Used for the main scene layer where individual
|
|
115
|
+
* shapes need cull toggling.
|
|
116
|
+
*/
|
|
117
|
+
export declare class DrawCommandLayerNode {
|
|
118
|
+
private readonly entries;
|
|
119
|
+
private readonly nodeToEntry;
|
|
120
|
+
private readonly konvaLayer;
|
|
121
|
+
private konvaShape;
|
|
122
|
+
constructor(konvaLayer: Konva.Layer);
|
|
123
|
+
addNode(node: RecordingGroupNode): void;
|
|
124
|
+
/** Return the DrawEntry created when `node` was added, or undefined if not found. */
|
|
125
|
+
getEntry(node: RecordingGroupNode): DrawEntry | undefined;
|
|
126
|
+
destroyChildren(): void;
|
|
127
|
+
batchDraw(): void;
|
|
128
|
+
private ensureShape;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Layer backed by a single Konva.Shape whose sceneFunc replays every added
|
|
132
|
+
* {@link RecordingGroupNode} in order. Used for layers that don't need
|
|
133
|
+
* per-shape cull toggling (grid, top-label).
|
|
134
|
+
*/
|
|
135
|
+
export declare class RecordingLayerNode {
|
|
136
|
+
private groups;
|
|
137
|
+
private readonly konvaLayer;
|
|
138
|
+
private konvaShape;
|
|
139
|
+
constructor(konvaLayer: Konva.Layer);
|
|
140
|
+
addNode(node: RecordingGroupNode): void;
|
|
141
|
+
destroyChildren(): void;
|
|
142
|
+
batchDraw(): void;
|
|
143
|
+
private ensureShape;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Layer that materializes each added {@link RecordingGroupNode} as its own
|
|
147
|
+
* `Konva.Group`. Used for layers where the renderer keeps a reference to
|
|
148
|
+
* each node (overlay highlights, position marker) so it can destroy them
|
|
149
|
+
* individually.
|
|
150
|
+
*/
|
|
151
|
+
export declare class MaterializingLayerNode {
|
|
152
|
+
private readonly konvaLayer;
|
|
153
|
+
constructor(konvaLayer: Konva.Layer);
|
|
154
|
+
addNode(node: RecordingGroupNode): void;
|
|
155
|
+
destroyChildren(): void;
|
|
156
|
+
batchDraw(): void;
|
|
157
|
+
}
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DrawCommandBatch } from '../draw/DrawCommand';
|
|
2
|
+
/**
|
|
3
|
+
* Convert one or more {@link DrawCommandBatch}es into SVG element strings, in
|
|
4
|
+
* the order they appear. Caller wraps the result in `<svg viewBox=…>` /
|
|
5
|
+
* `</svg>` and inserts a background rect.
|
|
6
|
+
*/
|
|
7
|
+
export declare function svgFromBatches(batches: DrawCommandBatch[]): string[];
|