glyphcss 0.0.1 → 0.0.3
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/dist/elements-DVWVBIG0.d.cts +313 -0
- package/dist/elements-DVWVBIG0.d.ts +313 -0
- package/dist/elements.cjs +30 -9
- package/dist/elements.d.cts +1 -1
- package/dist/elements.d.ts +1 -1
- package/dist/elements.js +30 -9
- package/dist/index.cjs +30 -9
- package/dist/index.d.cts +114 -36
- package/dist/index.d.ts +114 -36
- package/dist/index.js +30 -9
- package/package.json +3 -3
- package/dist/elements-Bb37NHHO.d.cts +0 -269
- package/dist/elements-Bb37NHHO.d.ts +0 -269
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { G as
|
|
2
|
-
export { e as
|
|
3
|
-
import { Hotspot, HotspotCell, GridSize, WireframeEdge, RenderMode, CharRamp } from '@glyphcss/core';
|
|
1
|
+
import { G as GlyphSceneHandle, a as GlyphCamera, b as GlyphDirectionalLight, c as GlyphAmbientLight } from './elements-DVWVBIG0.js';
|
|
2
|
+
export { d as GlyphHotspotElement, e as GlyphHotspotHandle, f as GlyphHotspotOptions, g as GlyphMapControlsElement, h as GlyphMeshElement, i as GlyphMeshHandle, j as GlyphMeshTransform, k as GlyphOrbitControlsElement, l as GlyphOrthographicCameraElement, m as GlyphOrthographicCameraHandle, n as GlyphOrthographicCameraOptions, o as GlyphPerspectiveCameraElement, p as GlyphPerspectiveCameraHandle, q as GlyphPerspectiveCameraOptions, r as GlyphSceneElement, s as GlyphSceneOptions, t as createGlyphCamera, u as createGlyphOrthographicCamera, v as createGlyphPerspectiveCamera, w as createGlyphScene } from './elements-DVWVBIG0.js';
|
|
3
|
+
import { Hotspot, HotspotCell, GridSize, Polygon, WireframeEdge, RenderMode, CharRamp } from '@glyphcss/core';
|
|
4
4
|
export * from '@glyphcss/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* createGlyphOrbitControls — orbit-mode camera input for a GlyphScene.
|
|
8
8
|
*
|
|
9
9
|
* Left-drag rotates rotX / rotY around the target (orbit). Wheel zooms or
|
|
10
|
-
* dollies. Mirrors
|
|
11
|
-
* the ASCII rasterizer's
|
|
10
|
+
* dollies. Mirrors glyphcss's createPolyOrbitControls semantics, adapted for
|
|
11
|
+
* the ASCII rasterizer's GlyphCamera instead of the CSS matrix3d camera.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
interface
|
|
14
|
+
interface GlyphOrbitControlsOptions {
|
|
15
15
|
/** Pointer-drag. Default: true. */
|
|
16
16
|
drag?: boolean;
|
|
17
17
|
/** Wheel / pinch zoom. Default: true. */
|
|
@@ -25,23 +25,23 @@ interface GlyphcssOrbitControlsOptions {
|
|
|
25
25
|
pauseOnInteraction?: boolean;
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
interface
|
|
29
|
-
update(opts:
|
|
28
|
+
interface GlyphOrbitControlsHandle {
|
|
29
|
+
update(opts: GlyphOrbitControlsOptions): void;
|
|
30
30
|
pause(): void;
|
|
31
31
|
resume(): void;
|
|
32
32
|
destroy(): void;
|
|
33
33
|
}
|
|
34
|
-
declare function
|
|
34
|
+
declare function createGlyphOrbitControls(scene: GlyphSceneHandle, options?: GlyphOrbitControlsOptions): GlyphOrbitControlsHandle;
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* createGlyphMapControls — map/pan-mode camera input for a GlyphScene.
|
|
38
38
|
*
|
|
39
39
|
* Left-drag pans the target (slippy-map semantics). Right-drag or
|
|
40
|
-
* Shift+left-drag orbits. Wheel zooms. Mirrors
|
|
41
|
-
* semantics, adapted for the ASCII rasterizer's
|
|
40
|
+
* Shift+left-drag orbits. Wheel zooms. Mirrors glyphcss's createPolyMapControls
|
|
41
|
+
* semantics, adapted for the ASCII rasterizer's GlyphCamera.
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
-
interface
|
|
44
|
+
interface GlyphMapControlsOptions {
|
|
45
45
|
drag?: boolean;
|
|
46
46
|
wheel?: boolean;
|
|
47
47
|
invert?: boolean | number;
|
|
@@ -51,35 +51,97 @@ interface GlyphcssMapControlsOptions {
|
|
|
51
51
|
pauseOnInteraction?: boolean;
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
interface
|
|
55
|
-
update(opts:
|
|
54
|
+
interface GlyphMapControlsHandle {
|
|
55
|
+
update(opts: GlyphMapControlsOptions): void;
|
|
56
56
|
pause(): void;
|
|
57
57
|
resume(): void;
|
|
58
58
|
destroy(): void;
|
|
59
59
|
}
|
|
60
|
-
declare function
|
|
60
|
+
declare function createGlyphMapControls(scene: GlyphSceneHandle, options?: GlyphMapControlsOptions): GlyphMapControlsHandle;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
63
|
+
* createGlyphFirstPersonControls — first-person camera input for a GlyphScene.
|
|
64
|
+
*
|
|
65
|
+
* Requires the scene to have a perspective camera. On attach, sets
|
|
66
|
+
* `camera.eyeMode = true` so the perspective projection switches to the
|
|
67
|
+
* eye-at-origin formulation (target = eye position, near-plane cull). On
|
|
68
|
+
* detach, restores `eyeMode = false`.
|
|
64
69
|
*
|
|
65
70
|
* Mouse-drag looks around (rotX/rotY). WASD or arrow keys move forward/backward/strafe.
|
|
66
|
-
* Mirrors polycss's createPolyFirstPersonControls semantics for the ASCII rasterizer.
|
|
67
71
|
*/
|
|
68
72
|
|
|
69
|
-
interface
|
|
73
|
+
interface GlyphFirstPersonControlsOptions {
|
|
70
74
|
drag?: boolean;
|
|
71
75
|
keyboard?: boolean;
|
|
72
76
|
moveSpeed?: number;
|
|
73
77
|
lookSpeed?: number;
|
|
74
78
|
invert?: boolean | number;
|
|
75
79
|
}
|
|
76
|
-
interface
|
|
77
|
-
update(opts:
|
|
80
|
+
interface GlyphFirstPersonControlsHandle {
|
|
81
|
+
update(opts: GlyphFirstPersonControlsOptions): void;
|
|
78
82
|
pause(): void;
|
|
79
83
|
resume(): void;
|
|
80
84
|
destroy(): void;
|
|
81
85
|
}
|
|
82
|
-
declare function
|
|
86
|
+
declare function createGlyphFirstPersonControls(scene: GlyphSceneHandle, options?: GlyphFirstPersonControlsOptions): GlyphFirstPersonControlsHandle;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Mesh lookup helpers — mirrors voxcss's `findPolyMeshHandle`,
|
|
90
|
+
* `findMeshUnderPoint`, and `pointInMeshElement`.
|
|
91
|
+
*
|
|
92
|
+
* `findGlyphMeshHandle(host, id)` performs an O(n) walk of mesh elements
|
|
93
|
+
* under the given host, matching on the `data-glyph-mesh-id` attribute.
|
|
94
|
+
*
|
|
95
|
+
* `findMeshUnderPoint` and `pointInMeshElement` use bounding-box checks.
|
|
96
|
+
* TODO(hit-layer): replace the bbox check with proper polygon raycasting once
|
|
97
|
+
* the rasterizer hit-map is wired to the hit layer.
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Given a host element and a string mesh id, return the mesh's HTMLElement
|
|
102
|
+
* (the `.glyph-mesh` wrapper div) if found, or `null`.
|
|
103
|
+
*/
|
|
104
|
+
declare function findGlyphMeshHandle(host: HTMLElement, id: string): HTMLElement | null;
|
|
105
|
+
/**
|
|
106
|
+
* Bbox check — returns true when (x, y) in client coordinates falls inside
|
|
107
|
+
* the bounding rect of `el`.
|
|
108
|
+
*
|
|
109
|
+
* TODO(hit-layer): replace with polygon-level raycasting once available.
|
|
110
|
+
*/
|
|
111
|
+
declare function pointInMeshElement(el: HTMLElement, clientX: number, clientY: number): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Returns the `.glyph-mesh` element whose bounding box contains the
|
|
114
|
+
* given client coordinates, or `null`.
|
|
115
|
+
*
|
|
116
|
+
* The `host` parameter scopes the search; pass the scene host element to
|
|
117
|
+
* avoid matching meshes from other scenes on the page.
|
|
118
|
+
*
|
|
119
|
+
* TODO(hit-layer): wire to rasterizer hit-map raycasting once available.
|
|
120
|
+
* Until then this returns a bbox-level approximation (not pixel-accurate).
|
|
121
|
+
*/
|
|
122
|
+
declare function findMeshUnderPoint(host: HTMLElement | Document, clientX: number, clientY: number): HTMLElement | null;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Typed DOM event aliases for mesh interaction.
|
|
126
|
+
*
|
|
127
|
+
* `meshId` is populated when the event originates from a hit-layer lookup —
|
|
128
|
+
* it carries the string id of the mesh that was hit (the `id` prop / transform
|
|
129
|
+
* `id`).
|
|
130
|
+
*
|
|
131
|
+
* TODO(hit-layer): meshId will be set automatically once the rasterizer
|
|
132
|
+
* hit-map and per-polygon raycasting are wired into the hit-layer dispatch.
|
|
133
|
+
* Until then, consumers receive plain DOM events with `meshId` left undefined.
|
|
134
|
+
*/
|
|
135
|
+
type GlyphPointerEvent = PointerEvent & {
|
|
136
|
+
meshId?: string;
|
|
137
|
+
};
|
|
138
|
+
type GlyphMouseEvent = MouseEvent & {
|
|
139
|
+
meshId?: string;
|
|
140
|
+
};
|
|
141
|
+
type GlyphWheelEvent = WheelEvent & {
|
|
142
|
+
meshId?: string;
|
|
143
|
+
};
|
|
144
|
+
type GlyphEventHandler<E = Event> = (event: E) => void;
|
|
83
145
|
|
|
84
146
|
/**
|
|
85
147
|
* Project a list of 3D hotspot anchors through the camera. Returns the
|
|
@@ -89,18 +151,18 @@ declare function createGlyphcssFirstPersonControls(scene: GlyphcssSceneHandle, o
|
|
|
89
151
|
* the renderer and hit layer cannot drift out of sync as long as they
|
|
90
152
|
* share a camera.
|
|
91
153
|
*/
|
|
92
|
-
declare function projectHotspots(hotspots: readonly Hotspot[], camera:
|
|
154
|
+
declare function projectHotspots(hotspots: readonly Hotspot[], camera: GlyphCamera, cols: number, rows: number, cellAspect: number): HotspotCell[];
|
|
93
155
|
|
|
94
156
|
interface RasterizeContextOptions {
|
|
95
|
-
camera:
|
|
157
|
+
camera: GlyphCamera;
|
|
96
158
|
grid: GridSize;
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
/** Explicit wireframe edges. If omitted in wireframe mode, edges are derived from `
|
|
159
|
+
/** Polygon list. Required for `solid` / `voxel` modes, optional otherwise. */
|
|
160
|
+
polygons?: Polygon[];
|
|
161
|
+
/** Explicit wireframe edges. If omitted in wireframe mode, edges are derived from `polygons` (fan-triangulated). */
|
|
100
162
|
wireframe?: WireframeEdge[];
|
|
101
163
|
mode?: RenderMode;
|
|
102
|
-
directionalLight?:
|
|
103
|
-
ambientLight?:
|
|
164
|
+
directionalLight?: GlyphDirectionalLight;
|
|
165
|
+
ambientLight?: GlyphAmbientLight;
|
|
104
166
|
/** Named wireframe glyph palette. Defaults to `"default"`. */
|
|
105
167
|
glyphPalette?: string;
|
|
106
168
|
/**
|
|
@@ -108,18 +170,34 @@ interface RasterizeContextOptions {
|
|
|
108
170
|
* output is just one text node — fastest possible DOM update. Default `true`.
|
|
109
171
|
*/
|
|
110
172
|
useColors?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Smooth (Gouraud) shading. When `true`, per-pixel Lambert intensity is
|
|
175
|
+
* interpolated from per-vertex normals (averaged across adjacent polygons
|
|
176
|
+
* within `creaseAngle`). Default `false` — flat shading is glyph's default
|
|
177
|
+
* because the facets are part of the ASCII aesthetic.
|
|
178
|
+
*/
|
|
179
|
+
smoothShading?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Crease angle in degrees for smooth shading. Vertex normals are averaged
|
|
182
|
+
* across adjacent faces whose normals diverge by less than this angle;
|
|
183
|
+
* edges sharper than this stay flat-shaded. `0` collapses to pure flat
|
|
184
|
+
* shading; `180` smooths every shared vertex. Default `60`.
|
|
185
|
+
*/
|
|
186
|
+
creaseAngle?: number;
|
|
111
187
|
}
|
|
112
188
|
interface RasterizeContext {
|
|
113
|
-
camera:
|
|
189
|
+
camera: GlyphCamera;
|
|
114
190
|
grid: GridSize;
|
|
115
|
-
|
|
191
|
+
polygons: Polygon[];
|
|
116
192
|
wireframe: WireframeEdge[];
|
|
117
193
|
mode: RenderMode;
|
|
118
|
-
directionalLight:
|
|
119
|
-
ambientLight:
|
|
194
|
+
directionalLight: GlyphDirectionalLight;
|
|
195
|
+
ambientLight: GlyphAmbientLight;
|
|
120
196
|
/** Named wireframe glyph palette passed to the rasterizer. */
|
|
121
197
|
glyphPalette: string;
|
|
122
198
|
useColors: boolean;
|
|
199
|
+
smoothShading: boolean;
|
|
200
|
+
creaseAngle: number;
|
|
123
201
|
}
|
|
124
202
|
declare function buildRasterizeContext(opts: RasterizeContextOptions): RasterizeContext;
|
|
125
203
|
|
|
@@ -172,6 +250,6 @@ declare const WIREFRAME_GLYPHS: WireframeGlyphTiers;
|
|
|
172
250
|
/** Look up a named wireframe palette, falling back to `default`. */
|
|
173
251
|
declare function getWireframeGlyphs(name: string): WireframeGlyphTiers;
|
|
174
252
|
|
|
175
|
-
declare function
|
|
253
|
+
declare function injectGlyphBaseStyles(doc?: Document): void;
|
|
176
254
|
|
|
177
|
-
export { DEFAULT_RAMP,
|
|
255
|
+
export { DEFAULT_RAMP, GlyphAmbientLight, GlyphCamera, GlyphDirectionalLight, type GlyphEventHandler, type GlyphFirstPersonControlsHandle, type GlyphFirstPersonControlsOptions, type GlyphMapControlsHandle, type GlyphMapControlsOptions, type GlyphMouseEvent, type GlyphOrbitControlsHandle, type GlyphOrbitControlsOptions, type GlyphPointerEvent, GlyphSceneHandle, type GlyphWheelEvent, type RasterizeContext, type RasterizeContextOptions, SOLID_RAMP, WIREFRAME_GLYPHS, WIREFRAME_PALETTES, type WireframeGlyphTiers, bakeFrames, buildRasterizeContext, createGlyphFirstPersonControls, createGlyphMapControls, createGlyphOrbitControls, findGlyphMeshHandle, findMeshUnderPoint, getWireframeGlyphs, injectGlyphBaseStyles, pointInMeshElement, projectHotspots, rasterize };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
function
|
|
2
|
-
`)}return r.join("")}function
|
|
3
|
-
`)}return
|
|
1
|
+
function Fe(n,t,e){let o=Math.cos(t),r=Math.sin(t),s=o*n[1]-r*n[0],i=r*n[1]+o*n[0],a=n[2],u=Math.cos(e),c=Math.sin(e),h=u*i-c*a,d=c*i+u*a;return[s,h,d]}function K(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:n.distance??3,zoom:n.zoom??.4,stretch:n.stretch??1,target:[0,0,0],eyeMode:!1,focal:5},[e,o]=n.center??[.5,.5];return{kind:"perspective",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get zoom(){return t.zoom},set zoom(r){t.zoom=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},get eyeMode(){return t.eyeMode},set eyeMode(r){t.eyeMode=r},project(r,s,i,a){let u=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],c=Fe(u,t.rotY,t.rotX);if(t.eyeMode){if(c[2]>=-.001)return[NaN,NaN,c[2]];let x=t.focal/-c[2],p=Math.min(s,i)*t.zoom*x,b=s*e+c[0]*p*a*t.stretch,l=i*o+c[1]*p;return[b,l,c[2]]}let h=30,d=1.5,f=c[2]*h,m=.001,g=1-f/t.distance;if(g<m)return[NaN,NaN,c[2]];let L=1/g,E=Math.min(s,i)*t.zoom*d*L,S=s*e+c[0]*E*a*t.stretch,A=i*o+c[1]*E;return[S,A,c[2]]}}}function ee(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:0,zoom:n.zoom??.4,stretch:1,target:[0,0,0]},[e,o]=n.center??[.5,.5];return{kind:"orthographic",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get zoom(){return t.zoom},set zoom(r){t.zoom=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},get eyeMode(){return!1},set eyeMode(r){},project(r,s,i,a){let u=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],c=Fe(u,t.rotY,t.rotX),d=Math.min(s,i)*t.zoom*1.5,f=s*e+c[0]*d*a*t.stretch,m=i*o+c[1]*d;return[f,m,c[2]]}}}var tt=ee;var nt={direction:[.5,.7,.5],intensity:1},rt={intensity:.4};function ot(n){let t=new Set,e=[];for(let o of n){let r=o.vertices;if(!(r.length<2))for(let s=0;s<r.length;s++){let i=r[s],a=r[(s+1)%r.length],u=`${i[0]},${i[1]},${i[2]}`,c=`${a[0]},${a[1]},${a[2]}`,h=u<c?`${u}|${c}`:`${c}|${u}`;if(t.has(h))continue;t.add(h);let d={from:i,to:a,weight:2};o.color&&(d.color=o.color),e.push(d)}}return e}function fe(n){let t=n.polygons??[],e=n.mode??(t.length?"solid":"wireframe"),o=n.wireframe??(e==="wireframe"?ot(t):[]);return{camera:n.camera,grid:n.grid,polygons:t,wireframe:o,mode:e,directionalLight:n.directionalLight??nt,ambientLight:n.ambientLight??rt,glyphPalette:n.glyphPalette??"default",useColors:n.useColors??!0,smoothShading:n.smoothShading??!1,creaseAngle:n.creaseAngle??60}}var it=" .:-=+*#%@".split(""),st=" .:-=+*#%@".split(""),te={default:{thin:"\xB7\u22C5\u2219\u02D9\xB7\u22C5\u2219".split(""),normal:"\u254B\u256C\u253C\u2573\u25C6\u25C7\u25CA\u25B2\u25B3\u25BC\u25BD\u25C8\u2B21\u2B22\u2234\u2235\u22A5\u2295\u2297\u2299\u229A\u229B".split(""),core:"\u2726\u2727\u2729\u25C9\u2299\u25CE".split(""),solid:" .:-=+*#%@".split("")},ascii:{thin:".'".split(""),normal:"+*x".split(""),core:"#@".split(""),solid:" .,:;!+=*xX#@".split("")},dots:{thin:"\xB7\u22C5".split(""),normal:"\u2022\u25CF".split(""),core:"\u25C9\u25CE".split(""),solid:" \xB7\u22C5\u2218\u2022\u25CF\u25C9\u25CE\u2B24".split("")},lines:{thin:"\u2500\u2502".split(""),normal:"\u2550\u2551".split(""),core:"\u2588".split(""),solid:" \u2500\u2550\u256C\u2551\u2588\u2593\u2592\u2591".split("")},blocks:{thin:"\u2591\u2581".split(""),normal:"\u2592\u2593\u258C\u2590\u2580\u2584".split(""),core:"\u2588".split(""),solid:" \u2591\u2592\u2593\u258C\u2590\u2588\u2580\u2584\u25A0".split("")},stars:{thin:"\xB7\u22C6".split(""),normal:"\u2726\u2727\u2729\u272A".split(""),core:"\u272B\u272C\u272D\u2605".split(""),solid:" \xB7\u22C6\u2217\u2726\u2727\u2729\u272A\u272B\u2605".split("")},arrows:{thin:"\xB7\u2219".split(""),normal:"\u2190\u2191\u2192\u2193".split(""),core:"\u2196\u2197\u2198\u2199\u2921\u2922".split(""),solid:" \xB7\u2219\u2191\u2197\u2192\u2198\u2193\u2199\u2190\u2196".split("")},braille:{thin:"\u2801\u2802\u2804\u2808".split(""),normal:"\u2803\u2805\u2806\u2809\u280A\u280B\u280C\u280D\u280E\u280F".split(""),core:"\u283F\u28FF".split(""),solid:" \u2801\u2803\u2807\u2827\u2837\u283F\u287F\u28FF".split("")},runes:{thin:".\xB7".split(""),normal:"\u16A0\u16A1\u16A2\u16A3\u16A4\u16A6\u16A8\u16B1\u16B2\u16B3\u16B7\u16B9\u16C3\u16C7\u16C9".split(""),core:"\u16DE\u16DF\u16E1\u16E2\u16E3".split(""),solid:" \xB7\u16A0\u16A3\u16A4\u16A8\u16B1\u16B7\u16DE\u16E2".split("")},math:{thin:"\u2219\u2218".split(""),normal:"\u2211\u220F\u222B\u221A\u221E\u2248\u2260\u2264\u2265\u2282\u2283\u2286\u2287".split(""),core:"\u222E\u222F\u2230\u2202".split(""),solid:" \u2219\u2218\u2211\u222B\u221A\u221E\u2248\u2295\u2297".split("")},binary:{thin:"\xB7.".split(""),normal:"01".split(""),core:"\u2588".split(""),solid:" .:01\u2588\u2588".split("")},hex:{thin:"\xB7\u2219".split(""),normal:"0123456789ABCDEF".split(""),core:"FFAA".split(""),solid:" 0123456789AF".split("")}},lt=te.default;function ne(n){return te[n]??te.default}function re(n){let{camera:t,grid:e,wireframe:o,mode:r}=n,{cols:s,rows:i,cellAspect:a}=e;if(r==="solid")return at(n,s,i,a);let u=ne(n.glyphPalette),c=new Uint8Array(s*i),h=n.useColors?new Array(s*i).fill(null):null;for(let d of o){let f=t.project(d.from,s,i,a),m=t.project(d.to,s,i,a);f[0]!==f[0]||m[0]!==m[0]||mt(c,h,f[0]|0,f[1]|0,m[0]|0,m[1]|0,d.weight??2,d.color??null,s,i)}return ft(c,h,s,i,u)}function at(n,t,e,o){let{camera:r,polygons:s,directionalLight:i,ambientLight:a,smoothShading:u,creaseAngle:c}=n,h=ne(n.glyphPalette).solid,d=h.length-1,f=new Array(t*e).fill(" "),m=n.useColors,g=m?new Array(t*e).fill(null):null,L=new Float64Array(t*e).fill(-1/0),E=i.direction,S=Math.hypot(E[0],E[1],E[2])||1,A=E[0]/S,M=E[1]/S,x=E[2]/S,p=i.intensity??1,b=a.intensity??.4,l=ye(i.color??"#ffffff"),v=ye(a.color??"#ffffff"),G=u&&c>0?dt(s,c):null;for(let C=0;C<s.length;C++){let y=s[C],w=y.vertices;if(!(w.length<3))for(let _=1;_<w.length-1;_++){let H=_,I=_+1,z=w[0],P=w[H],F=w[I],O=r.project(z,t,e,o),k=r.project(P,t,e,o),Y=r.project(F,t,e,o);if(O[0]!==O[0]||k[0]!==k[0]||Y[0]!==Y[0])continue;let D=P[0]-z[0],B=P[1]-z[1],oe=P[2]-z[2],$=F[0]-z[0],N=F[1]-z[1],J=F[2]-z[2],Q=B*J-oe*N,j=oe*$-D*J,Pe=D*N-B*$,ie=Math.hypot(Q,j,Pe)||1,Be=Q/ie,We=j/ie,$e=Pe/ie,se,le,ae,ce,ue,de,pe,he,me;if(G){let U=G[C],X=U[0],V=U[H],q=U[I];se=X[0],le=X[1],ae=X[2],ce=V[0],ue=V[1],de=V[2],pe=q[0],he=q[1],me=q[2]}else se=ce=pe=Be,le=ue=he=We,ae=de=me=$e;let je=se*A+le*M+ae*x,Ue=ce*A+ue*M+de*x,qe=pe*A+he*M+me*x,Oe=Math.min(1,b+Math.max(0,je)*p),ke=Math.min(1,b+Math.max(0,Ue)*p),Re=Math.min(1,b+Math.max(0,qe)*p),Ie=null;if(m){let U=(Oe+ke+Re)/3,X=Math.max(0,U-b),V=y.color?ye(y.color):[255,255,255],q=b*v[0]/255+X*l[0]/255,Ke=b*v[1]/255+X*l[1]/255,Ze=b*v[2]/255+X*l[2]/255,Je=Math.min(255,V[0]*q),Qe=Math.min(255,V[1]*Ke),et=Math.min(255,V[2]*Ze);Ie=`#${ge(Je)}${ge(Qe)}${ge(et)}`}ut(O[0],O[1],O[2],Oe,k[0],k[1],k[2],ke,Y[0],Y[1],Y[2],Re,h,d,Ie,f,g,L,t,e)}}return pt(f,g,t,e)}var ct=new Float64Array([(0+.5)/16,(8+.5)/16,(2+.5)/16,(10+.5)/16,(12+.5)/16,(4+.5)/16,(14+.5)/16,(6+.5)/16,(3+.5)/16,(11+.5)/16,(1+.5)/16,(9+.5)/16,(15+.5)/16,(7+.5)/16,(13+.5)/16,(5+.5)/16]);function ut(n,t,e,o,r,s,i,a,u,c,h,d,f,m,g,L,E,S,A,M){let x=(r-n)*(c-t)-(s-t)*(u-n);if(x===0||x>0)return;let p=1/x,b=x>0,l=n<r?n:r;u<l&&(l=u);let v=n>r?n:r;u>v&&(v=u);let G=t<s?t:s;c<G&&(G=c);let C=t>s?t:s;c>C&&(C=c);let y=Math.max(0,Math.ceil(l)),w=Math.min(A-1,Math.floor(v)),_=Math.max(0,Math.ceil(G)),T=Math.min(M-1,Math.floor(C));if(!(y>w||_>T))for(let H=_;H<=T;H++){let I=H;for(let z=y;z<=w;z++){let P=z,F=(r-P)*(c-I)-(s-I)*(u-P),O=(u-P)*(t-I)-(c-I)*(n-P),k=(n-P)*(s-I)-(t-I)*(r-P);if(b?F<0||O<0||k<0:F>0||O>0||k>0)continue;let Y=(F*e+O*i+k*h)*p,D=H*A+z;if(Y>S[D]){S[D]=Y;let B=(F*o+O*a+k*d)*p,$=(B<0?0:B>1?1:B)*m,N=$|0,J=$-N,Q=ct[(H&3)*4+(z&3)],j=J>Q&&N<m?N+1:N;L[D]=f[j>m?m:j],E&&(E[D]=g)}}}}function dt(n,t){let e=n.length,o=new Array(e);for(let a=0;a<e;a++){let u=n[a].vertices;if(u.length<3){o[a]=[0,0,0];continue}let c=u[0],h=u[1],d=u[2],f=h[0]-c[0],m=h[1]-c[1],g=h[2]-c[2],L=d[0]-c[0],E=d[1]-c[1],S=d[2]-c[2],A=m*S-g*E,M=g*L-f*S,x=f*E-m*L,p=Math.hypot(A,M,x)||1;o[a]=[A/p,M/p,x/p]}let r=new Map;for(let a=0;a<e;a++){let u=n[a].vertices;for(let c=0;c<u.length;c++){let h=u[c],d=`${h[0]},${h[1]},${h[2]}`,f=r.get(d);f||(f=[],r.set(d,f)),(f.length===0||f[f.length-1]!==a)&&f.push(a)}}let s=Math.cos(t*Math.PI/180),i=new Array(e);for(let a=0;a<e;a++){let u=n[a].vertices,c=o[a],h=new Array(u.length);for(let d=0;d<u.length;d++){let f=u[d],m=r.get(`${f[0]},${f[1]},${f[2]}`),g=0,L=0,E=0;for(let A=0;A<m.length;A++){let M=m[A],x=o[M];c[0]*x[0]+c[1]*x[1]+c[2]*x[2]>=s&&(g+=x[0],L+=x[1],E+=x[2])}let S=Math.hypot(g,L,E)||1;h[d]=[g/S,L/S,E/S]}i[a]=h}return i}function pt(n,t,e,o){let r=[],s=null,i="",a=()=>{i&&(s!==null?r.push(`<span style="color:${s}">${i}</span>`):r.push(i),i="")};for(let u=0;u<o;u++){for(let c=0;c<e;c++){let h=u*e+c,d=n[h],f=t&&d!==" "?t[h]??null:null;f!==s&&(a(),s=f),i+=d}a(),s=null,u<o-1&&r.push(`
|
|
2
|
+
`)}return r.join("")}function ht(n,t,e="y"){let{camera:o}=n,r=e==="y"?o.rotY:o.rotX,s=new Array(t);for(let i=0;i<t;i++){let a=r+i/t*Math.PI*2;e==="y"?o.rotY=a:o.rotX=a,s[i]=re(n)}return e==="y"?o.rotY=r:o.rotX=r,s}function mt(n,t,e,o,r,s,i,a,u,c){let h=Math.abs(r-e),d=-Math.abs(s-o),f=e<r?1:-1,m=o<s?1:-1,g=h+d;for(;;){if(e>=0&&e<u&&o>=0&&o<c){let E=o*u+e;n[E]<i&&(n[E]=i,t&&(t[E]=a))}if(e===r&&o===s)break;let L=2*g;L>=d&&(g+=d,e+=f),L<=h&&(g+=h,o+=m)}}function ft(n,t,e,o,r){let s=[],i=null,a="",u=()=>{a&&(i!==null?s.push(`<span style="color:${i}">${a}</span>`):s.push(a),a="")};for(let c=0;c<o;c++){for(let h=0;h<e;h++){let d=c*e+h,f=n[d],m,g;f===0?(m=" ",g=null):(m=f===1?r.thin[Math.random()*r.thin.length|0]:f===2?r.normal[Math.random()*r.normal.length|0]:r.core[Math.random()*r.core.length|0],g=t?t[d]??null:null),g!==i&&(u(),i=g),a+=m}u(),i=null,c<o-1&&s.push(`
|
|
3
|
+
`)}return s.join("")}function ye(n){let t=n.startsWith("#")?n.slice(1):n;if(t.length===3){let e=parseInt(t[0]+t[0],16),o=parseInt(t[1]+t[1],16),r=parseInt(t[2]+t[2],16);return[e||0,o||0,r||0]}if(t.length===6){let e=parseInt(t.slice(0,2),16),o=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16);return[e||0,o||0,r||0]}return[255,255,255]}function ge(n){let t=Math.max(0,Math.min(255,n|0)).toString(16);return t.length===1?"0"+t:t}var Ye="glyph-styles";function be(n){let t=n??(typeof document<"u"?document:void 0);if(!t||t.getElementById(Ye))return;let e=t.createElement("style");e.id=Ye,e.textContent=yt,t.head.appendChild(e)}var yt=`
|
|
4
|
+
/* \u2500\u2500 React / Vue host wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
5
|
+
|
|
6
|
+
.glyph-host {
|
|
7
|
+
/* Fill the camera wrapper so autoSize can observe a non-zero height. */
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
/* \u2500\u2500 Glyphcss scene container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
5
13
|
|
|
6
|
-
.
|
|
14
|
+
.glyph-scene {
|
|
7
15
|
position: relative;
|
|
8
16
|
display: block;
|
|
9
17
|
overflow: hidden;
|
|
@@ -12,8 +20,12 @@ function D(n,t,e){let s=Math.cos(t),r=Math.sin(t),c=s*n[1]-r*n[0],o=r*n[1]+s*n[0
|
|
|
12
20
|
|
|
13
21
|
/* \u2500\u2500 ASCII output <pre> \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
14
22
|
|
|
15
|
-
.
|
|
16
|
-
display:
|
|
23
|
+
.glyph-scene .glyph-output {
|
|
24
|
+
/* inline-block so the box shrinks to the text's natural width. With display:
|
|
25
|
+
block the pre inherits parent width, leaving empty space on the right, and
|
|
26
|
+
cellW = preRect.width / cols overshoots the actual character cell \u2014 placing
|
|
27
|
+
hotspots to the right of the rasterized glyph they're supposed to anchor. */
|
|
28
|
+
display: inline-block;
|
|
17
29
|
margin: 0;
|
|
18
30
|
padding: 0;
|
|
19
31
|
font-family: monospace;
|
|
@@ -27,15 +39,24 @@ function D(n,t,e){let s=Math.cos(t),r=Math.sin(t),c=s*n[1]-r*n[0],o=r*n[1]+s*n[0
|
|
|
27
39
|
|
|
28
40
|
/* \u2500\u2500 Hotspot overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
29
41
|
|
|
30
|
-
.
|
|
42
|
+
.glyph-scene .glyph-hotspot-layer {
|
|
31
43
|
position: absolute;
|
|
32
44
|
inset: 0;
|
|
33
45
|
pointer-events: none;
|
|
46
|
+
/* Isolate the stacking context so per-hotspot z-index values (derived from
|
|
47
|
+
camera depth, sometimes negative) stay scoped INSIDE the layer. Without
|
|
48
|
+
this, a negative-z-index hotspot would render below the sibling <pre>,
|
|
49
|
+
hidden behind the rasterized glyphs. */
|
|
50
|
+
isolation: isolate;
|
|
34
51
|
}
|
|
35
52
|
|
|
36
|
-
.
|
|
53
|
+
.glyph-scene .glyph-hotspot {
|
|
37
54
|
position: absolute;
|
|
38
55
|
pointer-events: all;
|
|
39
56
|
cursor: pointer;
|
|
57
|
+
/* Center the label on the projected anchor point rather than anchoring its
|
|
58
|
+
top-left corner there. Without this, padding / label width visually offset
|
|
59
|
+
the content from the 3D vertex being labelled. */
|
|
60
|
+
transform: translate(-50%, -50%);
|
|
40
61
|
}
|
|
41
|
-
`;function W(n,t,e,s,r){return n.map(c=>{let[o,a,p]=t.project(c.at,e,s,r),l=p>-3&&o>=0&&o<e&&a>=0&&a<s;return{id:c.id,col:o,row:a,depth:p,visible:l}})}var Be=1;function je(n,t){let{position:e,scale:s,rotation:r}=t;if(!e&&!s&&!r)return n;let[c,o,a]=e??[0,0,0],p=1,l=1,y=1;s!==void 0&&(typeof s=="number"?p=l=y=s:[p,l,y]=s);let[u,b,f]=r??[0,0,0],d=Math.cos(u),M=Math.sin(u),E=Math.cos(b),T=Math.sin(b),h=Math.cos(f),v=Math.sin(f);function G(C){let g=C[0]*p,i=C[1]*l,x=C[2]*y,L=h*g-v*i,A=v*g+h*i,m=x;return g=E*L+T*m,i=A,x=-T*L+E*m,L=g,A=d*i-M*x,m=M*i+d*x,[L+c,A+o,m+a]}return n.map(C=>({...C,vertices:[G(C.vertices[0]),G(C.vertices[1]),G(C.vertices[2])]}))}function U(n,t={}){j(n.ownerDocument??void 0);let e={mode:t.mode??"solid",glyphPalette:t.glyphPalette??"default",useColors:t.useColors??!0,cols:t.cols??80,rows:t.rows??24,cellAspect:t.cellAspect??2,directionalLight:t.directionalLight??{direction:[.5,.7,.5],intensity:1},ambientLight:t.ambientLight??{intensity:.4},camera:t.camera??w()},s=n.ownerDocument.createElement("div");s.className="glyphcss-scene";let r=n.ownerDocument.createElement("pre");r.className="glyphcss-output";let c=n.ownerDocument.createElement("div");c.className="glyphcss-hotspot-layer",s.appendChild(r),s.appendChild(c),n.appendChild(s);let o=new Map,a=[],p=!1;function l(){p||(p=!0,Promise.resolve().then(()=>{p=!1,y()}))}function y(){let h=[];for(let C of o.values()){let g=je(C.triangles,C.transform);for(let i of g)h.push(i)}let v=V({camera:e.camera,grid:{cols:e.cols,rows:e.rows,cellAspect:e.cellAspect},triangles:h,mode:e.mode,directionalLight:e.directionalLight,ambientLight:e.ambientLight,glyphPalette:e.glyphPalette,useColors:e.useColors}),G=Y(v);e.useColors?r.innerHTML=G:r.textContent=G,u()}function u(){let{cols:h,rows:v,cellAspect:G,camera:C}=e,g=W(a.map(A=>A.hotspot),C,h,v,G),i=r.getBoundingClientRect(),x=h>0?i.width/h:8,L=v>0?i.height/v:16;for(let A=0;A<a.length;A++){let{el:m}=a[A],S=g[A];S.visible?(m.style.display="",m.style.left=`${S.col*x}px`,m.style.top=`${S.row*L}px`,m.style.zIndex=String(Math.round(S.depth*1e3))):m.style.display="none"}}function b(h,v={}){let G=Be++;return o.set(G,{id:G,triangles:h,transform:v}),l(),{get id(){return G},get triangles(){return h},setTransform(C){let g=o.get(G);g&&(g.transform=C,l())},dispose(){o.delete(G),l()}}}function f(h,v){let G=n.ownerDocument.createElement("div");G.className="glyphcss-hotspot",G.setAttribute("data-hotspot-id",h.id);let[C,g]=h.size??[1,1];G.style.position="absolute",G.style.width=`${C}ch`,G.style.height=`${g*e.cellAspect}ch`,v&&G.addEventListener("click",v),c.appendChild(G);let i={hotspot:{id:h.id,at:h.at,size:h.size},el:G,onClick:v};return a.push(i),l(),{remove(){let x=a.indexOf(i);x>=0&&a.splice(x,1),v&&G.removeEventListener("click",v),c.removeChild(G),l()}}}function d(){y()}function M(h){h.mode!==void 0&&(e.mode=h.mode),h.glyphPalette!==void 0&&(e.glyphPalette=h.glyphPalette),h.useColors!==void 0&&(e.useColors=h.useColors),h.cols!==void 0&&(e.cols=h.cols),h.rows!==void 0&&(e.rows=h.rows),h.cellAspect!==void 0&&(e.cellAspect=h.cellAspect),h.directionalLight!==void 0&&(e.directionalLight=h.directionalLight),h.ambientLight!==void 0&&(e.ambientLight=h.ambientLight),h.camera!==void 0&&(e.camera=h.camera),l()}function E(){return{...e}}function T(){o.clear(),n.contains(s)&&n.removeChild(s)}return l(),{get host(){return n},get output(){return r},get camera(){return e.camera},add:b,addHotspot:f,rerender:d,setOptions:M,getOptions:E,destroy:T}}function q(n,t={}){let e=n.host,s=t.drag??!0,r=t.wheel??!0,c=fe(t.invert),o=t.animate??!1,a=!1,p=!1,l=null,y=null,u=null,b={x:0,y:0},f=n.camera;function d(i){if(!(!s||a)&&u===null&&i.isPrimary!==!1){i.preventDefault(),u=i.pointerId,b={x:i.clientX,y:i.clientY},e.style.cursor="grabbing";try{i.target.setPointerCapture(i.pointerId)}catch{}o&&o.pauseOnInteraction!==!1&&(p=!0)}}function M(i){if(u===null||i.pointerId!==u||!s||a)return;i.preventDefault();let x=i.clientX-b.x,L=i.clientY-b.y;b={x:i.clientX,y:i.clientY};let A=c,S=1/4*Math.PI/180;f.rotY=f.rotY-x*S*A,f.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,f.rotX+L*S*A)),n.rerender()}function E(i){if(u===i.pointerId){u=null,e.style.cursor=s&&!a?"grab":"";try{i.target.releasePointerCapture(i.pointerId)}catch{}o&&(p=!1)}}function T(i){if(!r||a)return;i.preventDefault();let x=i.deltaY*.001;f.scale=Math.max(.05,Math.min(10,f.scale*(1-x))),n.rerender()}function h(i){if(!(a||!o)){if(!p){let x=y!==null?Math.min(i-y,50):16.67,L=typeof o=="object"&&o.speed?o.speed:.3,A=typeof o=="object"&&o.axis?o.axis:"y",m=L*(Math.PI/180)*(x/16.67);A==="y"?f.rotY=f.rotY+m:f.rotX=f.rotX+m,n.rerender()}y=i,l=requestAnimationFrame(h)}}function v(){l===null&&typeof requestAnimationFrame<"u"&&o&&(l=requestAnimationFrame(h))}function G(){l!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(l),l=null),y=null}function C(){e.addEventListener("pointerdown",d),e.addEventListener("pointermove",M),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),e.addEventListener("wheel",T,{passive:!1}),e.style.cursor=s?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function g(){e.removeEventListener("pointerdown",d),e.removeEventListener("pointermove",M),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.removeEventListener("wheel",T),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return C(),v(),{update(i){let x=!!o;s=i.drag??s,r=i.wheel??r,c=fe(i.invert),o=i.animate??o,!a&&u===null&&(e.style.cursor=s?"grab":"");let L=!!o;x&&!L?G():!x&&L&&v()},pause(){a||(a=!0,g(),G(),u=null,p=!1)},resume(){a&&(a=!1,C(),v())},destroy(){a||g(),G(),a=!0}}}function fe(n){return n===void 0||n===!1?1:n===!0?-1:n}function $(n,t={}){let e=n.host,s=t.drag??!0,r=t.wheel??!0,c=ye(t.invert),o=t.animate??!1,a=!1,p=!1,l=null,y=null,u=null,b={x:0,y:0},f=!1,d=n.camera,M=1/4*Math.PI/180,E=.02;function T(m){if(!(!s||a)&&u===null&&m.isPrimary!==!1){m.preventDefault(),u=m.pointerId,b={x:m.clientX,y:m.clientY},f=m.button===2,e.style.cursor="grabbing";try{m.target.setPointerCapture(m.pointerId)}catch{}o&&o.pauseOnInteraction!==!1&&(p=!0)}}function h(m){if(u===null||m.pointerId!==u||!s||a)return;m.preventDefault();let S=m.clientX-b.x,_=m.clientY-b.y;b={x:m.clientX,y:m.clientY};let P=c;if(f||m.shiftKey)d.rotY=d.rotY-S*M*P,d.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,d.rotX+_*M*P));else{let H=d.target;d.target=[H[0]-S*E/d.scale,H[1]-_*E/d.scale,H[2]]}n.rerender()}function v(m){if(u===m.pointerId){u=null,f=!1,e.style.cursor=s&&!a?"grab":"";try{m.target.releasePointerCapture(m.pointerId)}catch{}o&&(p=!1)}}function G(m){m.preventDefault()}function C(m){if(!r||a)return;m.preventDefault();let S=m.deltaY*.001;d.scale=Math.max(.05,Math.min(10,d.scale*(1-S))),n.rerender()}function g(m){if(!(a||!o)){if(!p){let S=y!==null?Math.min(m-y,50):16.67,_=typeof o=="object"&&o.speed?o.speed:.3,P=typeof o=="object"&&o.axis?o.axis:"y",H=_*(Math.PI/180)*(S/16.67);P==="y"?d.rotY=d.rotY+H:d.rotX=d.rotX+H,n.rerender()}y=m,l=requestAnimationFrame(g)}}function i(){l===null&&typeof requestAnimationFrame<"u"&&o&&(l=requestAnimationFrame(g))}function x(){l!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(l),l=null),y=null}function L(){e.addEventListener("pointerdown",T),e.addEventListener("pointermove",h),e.addEventListener("pointerup",v),e.addEventListener("pointercancel",v),e.addEventListener("contextmenu",G),e.addEventListener("wheel",C,{passive:!1}),e.style.cursor=s?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function A(){e.removeEventListener("pointerdown",T),e.removeEventListener("pointermove",h),e.removeEventListener("pointerup",v),e.removeEventListener("pointercancel",v),e.removeEventListener("contextmenu",G),e.removeEventListener("wheel",C),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return L(),i(),{update(m){let S=!!o;s=m.drag??s,r=m.wheel??r,c=ye(m.invert),o=m.animate??o,!a&&u===null&&(e.style.cursor=s?"grab":"");let _=!!o;S&&!_?x():!S&&_&&i()},pause(){a||(a=!0,A(),x(),u=null,p=!1)},resume(){a&&(a=!1,L(),i())},destroy(){a||A(),x(),a=!0}}}function ye(n){return n===void 0||n===!1?1:n===!0?-1:n}function We(n,t={}){let e=n.host,s=t.drag??!0,r=t.keyboard??!0,c=t.moveSpeed??.05,o=t.lookSpeed??.004,a=ge(t.invert),p=!1,l=null,y={x:0,y:0},u=new Set,b=null,f=n.camera;function d(i){if(!(!s||p)&&l===null){i.preventDefault(),l=i.pointerId,y={x:i.clientX,y:i.clientY};try{i.target.setPointerCapture(i.pointerId)}catch{}}}function M(i){if(l===null||i.pointerId!==l||!s||p)return;i.preventDefault();let x=i.clientX-y.x,L=i.clientY-y.y;y={x:i.clientX,y:i.clientY},f.rotY=f.rotY-x*o*a,f.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,f.rotX+L*o*a)),n.rerender()}function E(i){if(l===i.pointerId){l=null;try{i.target.releasePointerCapture(i.pointerId)}catch{}}}function T(i){r&&!p&&u.add(i.key.toLowerCase())}function h(i){u.delete(i.key.toLowerCase())}function v(){if(p||!r||u.size===0)return;let i=f.target,x=Math.cos(f.rotY),L=Math.sin(f.rotY),A=!1;(u.has("w")||u.has("arrowup"))&&(f.target=[i[0]-L*c,i[1]-x*c,i[2]],A=!0),(u.has("s")||u.has("arrowdown"))&&(f.target=[i[0]+L*c,i[1]+x*c,i[2]],A=!0),(u.has("a")||u.has("arrowleft"))&&(f.target=[i[0]-x*c,i[1]+L*c,i[2]],A=!0),(u.has("d")||u.has("arrowright"))&&(f.target=[i[0]+x*c,i[1]-L*c,i[2]],A=!0),A&&n.rerender()}function G(){p||(v(),b=requestAnimationFrame(G))}function C(){e.addEventListener("pointerdown",d),e.addEventListener("pointermove",M),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),r&&(e.ownerDocument?.addEventListener("keydown",T),e.ownerDocument?.addEventListener("keyup",h)),e.style.touchAction="none",e.style.userSelect="none",typeof requestAnimationFrame<"u"&&(b=requestAnimationFrame(G))}function g(){e.removeEventListener("pointerdown",d),e.removeEventListener("pointermove",M),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.ownerDocument?.removeEventListener("keydown",T),e.ownerDocument?.removeEventListener("keyup",h),e.style.touchAction="",e.style.userSelect="",b!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(b),b=null),u.clear()}return C(),{update(i){s=i.drag??s,r=i.keyboard??r,c=i.moveSpeed??c,o=i.lookSpeed??o,a=ge(i.invert)},pause(){p||(p=!0,g(),l=null)},resume(){p&&(p=!1,C())},destroy(){p||g(),p=!0}}}function ge(n){return n===void 0||n===!1?1:n===!0?-1:n}var Ue=typeof HTMLElement<"u"?HTMLElement:class{},qe=["mode","glyph-palette","use-colors","cols","rows","cell-aspect","directional-direction","directional-intensity","ambient-intensity"];function O(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function $e(n){if(n==="wireframe"||n==="solid"||n==="voxel")return n}function Ze(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}var Z=class extends Ue{constructor(){super(...arguments);this._scene=null}static get observedAttributes(){return[...qe]}getScene(){return this._scene}_readOptions(){let e={},s=$e(this.getAttribute("mode"));s!==void 0&&(e.mode=s);let r=this.getAttribute("glyph-palette");r&&(e.glyphPalette=r);let c=Ze(this.getAttribute("use-colors"));c!==void 0&&(e.useColors=c);let o=O(this.getAttribute("cols"));o!==void 0&&(e.cols=o);let a=O(this.getAttribute("rows"));a!==void 0&&(e.rows=a);let p=O(this.getAttribute("cell-aspect"));p!==void 0&&(e.cellAspect=p);let l=O(this.getAttribute("directional-intensity"));l!==void 0&&(e.directionalLight={direction:[.5,.7,.5],intensity:l});let y=O(this.getAttribute("ambient-intensity"));return y!==void 0&&(e.ambientLight={intensity:y}),e}connectedCallback(){this._scene||(this._scene=U(this,this._readOptions()),this.dispatchEvent(new CustomEvent("glyphcss:scene-ready",{bubbles:!1})))}disconnectedCallback(){this._scene&&(this._scene.destroy(),this._scene=null)}attributeChangedCallback(e,s,r){s!==r&&this._scene&&this._scene.setOptions(this._readOptions())}};import{loadMesh as Ke}from"@glyphcss/core";var Je=typeof HTMLElement<"u"?HTMLElement:class{},Qe=["src","position","scale","rotation"];function K(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function et(n){if(n){if(!n.includes(",")){let t=parseFloat(n);return Number.isFinite(t)?t:void 0}return K(n)}}function tt(n){return n.closest("glyphcss-scene")??null}function nt(n){let t=[[0,0],[0,0],[0,0]],e=[];for(let s of n){let r=s.vertices;if(!(r.length<3))for(let c=1;c<r.length-1;c++)e.push({vertices:[r[0],r[c],r[c+1]],uvs:t,...s.color?{color:s.color}:{}})}return e}var J=class extends Je{constructor(){super(...arguments);this._handle=null;this._loadToken=0}static get observedAttributes(){return[...Qe]}getMeshHandle(){return this._handle}connectedCallback(){this._maybeLoad()}disconnectedCallback(){this._tearDown()}attributeChangedCallback(e,s,r){if(s!==r){if(e==="src"){this._tearDown(),this._maybeLoad();return}this._handle&&this._handle.setTransform(this._readTransform())}}_readTransform(){return{position:K(this.getAttribute("position")),scale:et(this.getAttribute("scale")),rotation:K(this.getAttribute("rotation"))}}_tearDown(){if(this._loadToken+=1,this._handle){try{this._handle.dispose()}catch{}this._handle=null}}async _maybeLoad(){let e=this.getAttribute("src");if(!e)return;let s=tt(this);if(!s)return;let r=++this._loadToken,c;try{c=await Ke(e)}catch(p){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:p,bubbles:!0}));return}if(r!==this._loadToken){try{c.dispose()}catch{}return}let o=s.getScene();if(!o){try{c.dispose()}catch{}return}let a=nt(c.polygons);this._handle=o.add(a,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{triangles:a},bubbles:!0}))}};var rt=typeof HTMLElement<"u"?HTMLElement:class{};function st(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function ot(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==2||t.some(e=>!Number.isFinite(e))))return[t[0],t[1]]}function it(n){return n.closest("glyphcss-scene")??null}var Q=class extends rt{constructor(){super(...arguments);this._handle=null}static get observedAttributes(){return["at","size","hotspot-id"]}connectedCallback(){this._register()}disconnectedCallback(){this._handle&&(this._handle.remove(),this._handle=null)}attributeChangedCallback(e,s,r){s!==r&&(this._handle&&(this._handle.remove(),this._handle=null),this._register())}_register(){let e=st(this.getAttribute("at"));if(!e)return;let r=it(this)?.getScene();if(!r)return;let c=this.getAttribute("hotspot-id")??this.getAttribute("id")??String(Math.random()),o=ot(this.getAttribute("size"));this._handle=r.addHotspot({id:c,at:e,size:o},()=>this.dispatchEvent(new CustomEvent("glyphcss:hotspot-click",{detail:{id:c},bubbles:!0})))}};var lt=typeof HTMLElement<"u"?HTMLElement:class{};function k(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function ct(n){return n.closest("glyphcss-scene")??null}var ee=class extends lt{static get observedAttributes(){return["rot-x","rot-y","distance","scale","stretch"]}connectedCallback(){this._apply()}attributeChangedCallback(t,e,s){e!==s&&this._apply()}_apply(){let e=ct(this)?.getScene();if(!e)return;let s=w({rotX:k(this.getAttribute("rot-x")),rotY:k(this.getAttribute("rot-y")),distance:k(this.getAttribute("distance")),scale:k(this.getAttribute("scale")),stretch:k(this.getAttribute("stretch"))});e.setOptions({camera:s})}};var at=typeof HTMLElement<"u"?HTMLElement:class{};function te(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function pt(n){return n.closest("glyphcss-scene")??null}var ne=class extends at{static get observedAttributes(){return["rot-x","rot-y","zoom"]}connectedCallback(){this._apply()}attributeChangedCallback(t,e,s){e!==s&&this._apply()}_apply(){let e=pt(this)?.getScene();if(!e)return;let s=z({rotX:te(this.getAttribute("rot-x")),rotY:te(this.getAttribute("rot-y")),zoom:te(this.getAttribute("zoom"))});e.setOptions({camera:s})}};var ut=typeof HTMLElement<"u"?HTMLElement:class{};function dt(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function re(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function ht(n){return n.closest("glyphcss-scene")??null}var se=class extends ut{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert","animate-speed","animate-axis"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,s,r){s!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=re(this.getAttribute("drag")),s=re(this.getAttribute("wheel")),r=re(this.getAttribute("invert")),c=dt(this.getAttribute("animate-speed")),o=this.getAttribute("animate-axis")==="x"?"x":"y";return{...e!==void 0?{drag:e}:{},...s!==void 0?{wheel:s}:{},...r!==void 0?{invert:r}:{},...c!==void 0?{animate:{speed:c,axis:o}}:{}}}_attach(){if(this._controls)return;let e=ht(this);if(!e)return;let s=e.getScene();if(!s){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=q(s,this._readOptions())}};var mt=typeof HTMLElement<"u"?HTMLElement:class{};function oe(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function ft(n){return n.closest("glyphcss-scene")??null}var ie=class extends mt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,s,r){s!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=oe(this.getAttribute("drag")),s=oe(this.getAttribute("wheel")),r=oe(this.getAttribute("invert"));return{...e!==void 0?{drag:e}:{},...s!==void 0?{wheel:s}:{},...r!==void 0?{invert:r}:{}}}_attach(){if(this._controls)return;let e=ft(this);if(!e)return;let s=e.getScene();if(!s){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=$(s,this._readOptions())}};export*from"@glyphcss/core";export{ke as DEFAULT_RAMP,Q as GlyphcssHotspotElement,ie as GlyphcssMapControlsElement,J as GlyphcssMeshElement,se as GlyphcssOrbitControlsElement,ne as GlyphcssOrthographicCameraElement,ee as GlyphcssPerspectiveCameraElement,Z as GlyphcssSceneElement,Re as SOLID_RAMP,Fe as WIREFRAME_GLYPHS,F as WIREFRAME_PALETTES,De as bakeFrames,V as buildRasterizeContext,He as createGlyphcssFirstPersonCamera,We as createGlyphcssFirstPersonControls,$ as createGlyphcssMapControls,q as createGlyphcssOrbitControls,z as createGlyphcssOrthographicCamera,w as createGlyphcssPerspectiveCamera,U as createGlyphcssScene,I as getWireframeGlyphs,j as injectGlyphcssBaseStyles,W as projectHotspots,Y as rasterize};
|
|
62
|
+
`;function ve(n,t,e,o,r){return n.map(s=>{let[i,a,u]=t.project(s.at,e,o,r),c=u>-3&&i>=0&&i<e&&a>=0&&a<o;return{id:s.id,col:i,row:a,depth:u,visible:c}})}var gt=1;function bt(n,t){let{position:e,scale:o,rotation:r}=t;if(!e&&!o&&!r)return n;let[s,i,a]=e??[0,0,0],u=1,c=1,h=1;o!==void 0&&(typeof o=="number"?u=c=h=o:[u,c,h]=o);let[d,f,m]=r??[0,0,0],g=Math.cos(d),L=Math.sin(d),E=Math.cos(f),S=Math.sin(f),A=Math.cos(m),M=Math.sin(m);function x(p){let b=p[0]*u,l=p[1]*c,v=p[2]*h,G=A*b-M*l,C=M*b+A*l,y=v;return b=E*G+S*y,l=C,v=-S*G+E*y,G=b,C=g*l-L*v,y=L*l+g*v,[G+s,C+i,y+a]}return n.map(p=>({...p,vertices:p.vertices.map(x)}))}function Ee(n,t={}){be(n.ownerDocument??void 0);let e={mode:t.mode??"solid",glyphPalette:t.glyphPalette??"default",useColors:t.useColors??!0,cols:t.cols??80,rows:t.rows??24,cellAspect:t.cellAspect??2,directionalLight:t.directionalLight??{direction:[.5,.7,.5],intensity:1},ambientLight:t.ambientLight??{intensity:.4},camera:t.camera??K(),smoothShading:t.smoothShading??!1,creaseAngle:t.creaseAngle??60,autoSize:t.autoSize??!1},o=n.ownerDocument.createElement("div");o.className="glyph-scene";let r=n.ownerDocument.createElement("pre");r.className="glyph-output";let s=n.ownerDocument.createElement("div");s.className="glyph-hotspot-layer",o.appendChild(r),o.appendChild(s),n.appendChild(o);let i=new Map,a=[],u=!1;function c(){u||(u=!0,Promise.resolve().then(()=>{u=!1,h()}))}function h(){let p=[];for(let v of i.values()){let G=bt(v.polygons,v.transform);for(let C of G)p.push(C)}let b=fe({camera:e.camera,grid:{cols:e.cols,rows:e.rows,cellAspect:e.cellAspect},polygons:p,mode:e.mode,directionalLight:e.directionalLight,ambientLight:e.ambientLight,glyphPalette:e.glyphPalette,useColors:e.useColors,smoothShading:e.smoothShading,creaseAngle:e.creaseAngle}),l=re(b);e.useColors?r.innerHTML=l:r.textContent=l,d()}function d(){let{cols:p,rows:b,cellAspect:l,camera:v}=e,G=ve(a.map(_=>_.hotspot),v,p,b,l),C=r.getBoundingClientRect(),y=p>0?C.width/p:8,w=b>0?C.height/b:16;for(let _=0;_<a.length;_++){let{el:T}=a[_],H=G[_];H.visible?(T.style.display="",T.style.left=`${(H.col+.5)*y}px`,T.style.top=`${(H.row+.5)*w}px`,T.style.zIndex=String(Math.round(H.depth*1e3))):T.style.display="none"}}function f(p,b={}){let l=gt++;return i.set(l,{id:l,polygons:p,transform:b}),c(),{get id(){return l},get name(){return i.get(l)?.transform.id},get polygons(){return p},setTransform(v){let G=i.get(l);G&&(G.transform=v,c())},dispose(){i.delete(l),c()}}}function m(p,b){let l=n.ownerDocument.createElement("div");l.className="glyph-hotspot",l.setAttribute("data-hotspot-id",p.id);let[v,G]=p.size??[1,1];l.style.position="absolute",l.style.width=`${v}ch`,l.style.height=`${G*e.cellAspect}ch`,b&&l.addEventListener("click",b),s.appendChild(l);let C={hotspot:{id:p.id,at:p.at,size:p.size},el:l,onClick:b};return a.push(C),c(),{get el(){return l},remove(){let y=a.indexOf(C);y>=0&&a.splice(y,1),b&&l.removeEventListener("click",b),s.removeChild(l),c()}}}function g(){h()}function L(p){p.mode!==void 0&&(e.mode=p.mode),p.glyphPalette!==void 0&&(e.glyphPalette=p.glyphPalette),p.useColors!==void 0&&(e.useColors=p.useColors),p.cols!==void 0&&(e.cols=p.cols),p.rows!==void 0&&(e.rows=p.rows),p.cellAspect!==void 0&&(e.cellAspect=p.cellAspect),p.directionalLight!==void 0&&(e.directionalLight=p.directionalLight),p.ambientLight!==void 0&&(e.ambientLight=p.ambientLight),p.camera!==void 0&&(e.camera=p.camera),p.smoothShading!==void 0&&(e.smoothShading=p.smoothShading),p.creaseAngle!==void 0&&(e.creaseAngle=p.creaseAngle),p.autoSize!==void 0&&(e.autoSize=p.autoSize,e.autoSize&&!M&&typeof ResizeObserver<"u"?(M=new ResizeObserver(()=>A()),M.observe(n),A()):!e.autoSize&&M&&(M.disconnect(),M=null)),c()}function E(){return{...e}}function S(){let p=n.ownerDocument.createElement("span");p.textContent="M",p.style.cssText="position:absolute;visibility:hidden;font-family:inherit;font-size:inherit;line-height:inherit;white-space:pre;padding:0;margin:0",r.appendChild(p);let b=p.getBoundingClientRect();return p.remove(),{w:b.width||8,h:b.height||16}}function A(){let p=n.clientWidth,b=n.clientHeight;if(!p||!b)return;let l=S(),v=Math.max(20,Math.floor(p/l.w)),G=Math.max(8,Math.floor(b/l.h)),C=l.h/l.w,y=!1;e.cols!==v&&(e.cols=v,y=!0),e.rows!==G&&(e.rows=G,y=!0),Math.abs(e.cellAspect-C)>.01&&(e.cellAspect=C,y=!0),y&&c()}let M=null;e.autoSize&&typeof ResizeObserver<"u"&&(M=new ResizeObserver(()=>A()),M.observe(n),A());function x(){M&&(M.disconnect(),M=null),i.clear(),n.contains(o)&&n.removeChild(o)}return c(),{get host(){return n},get output(){return r},get camera(){return e.camera},add:f,addHotspot:m,rerender:g,setOptions:L,getOptions:E,fit:A,destroy:x}}function Ge(n,t={}){let e=n.host,o=t.drag??!0,r=t.wheel??!0,s=De(t.invert),i=t.animate??!1,a=!1,u=!1,c=null,h=null,d=null,f={x:0,y:0},m=n.camera;function g(l){if(!(!o||a)&&d===null&&l.isPrimary!==!1){l.preventDefault(),d=l.pointerId,f={x:l.clientX,y:l.clientY},e.style.cursor="grabbing";try{l.target.setPointerCapture(l.pointerId)}catch{}i&&i.pauseOnInteraction!==!1&&(u=!0)}}function L(l){if(d===null||l.pointerId!==d||!o||a)return;l.preventDefault();let v=l.clientX-f.x,G=l.clientY-f.y;f={x:l.clientX,y:l.clientY};let C=s,w=1/4*Math.PI/180;m.rotY=m.rotY-v*w*C,m.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,m.rotX-G*w*C)),n.rerender()}function E(l){if(d===l.pointerId){d=null,e.style.cursor=o&&!a?"grab":"";try{l.target.releasePointerCapture(l.pointerId)}catch{}i&&(u=!1)}}function S(l){if(!r||a)return;l.preventDefault();let v=l.deltaY*.001;m.zoom=Math.max(.05,Math.min(10,m.zoom*(1-v))),n.rerender()}function A(l){if(!(a||!i)){if(!u){let v=h!==null?Math.min(l-h,50):16.67,G=typeof i=="object"&&i.speed?i.speed:.3,C=typeof i=="object"&&i.axis?i.axis:"y",y=G*(Math.PI/180)*(v/16.67);C==="y"?m.rotY=m.rotY+y:m.rotX=m.rotX+y,n.rerender()}h=l,c=requestAnimationFrame(A)}}function M(){c===null&&typeof requestAnimationFrame<"u"&&i&&(c=requestAnimationFrame(A))}function x(){c!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(c),c=null),h=null}function p(){e.addEventListener("pointerdown",g),e.addEventListener("pointermove",L),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),e.addEventListener("wheel",S,{passive:!1}),e.style.cursor=o?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function b(){e.removeEventListener("pointerdown",g),e.removeEventListener("pointermove",L),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.removeEventListener("wheel",S),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return p(),M(),{update(l){let v=!!i;o=l.drag??o,r=l.wheel??r,s=De(l.invert),i=l.animate??i,!a&&d===null&&(e.style.cursor=o?"grab":"");let G=!!i;v&&!G?x():!v&&G&&M()},pause(){a||(a=!0,b(),x(),d=null,u=!1)},resume(){a&&(a=!1,p(),M())},destroy(){a||b(),x(),a=!0}}}function De(n){return n===void 0||n===!1?1:n===!0?-1:n}function Me(n,t={}){let e=n.host,o=t.drag??!0,r=t.wheel??!0,s=Ne(t.invert),i=t.animate??!1,a=!1,u=!1,c=null,h=null,d=null,f={x:0,y:0},m=!1,g=n.camera,L=1/4*Math.PI/180,E=.02;function S(y){if(!(!o||a)&&d===null&&y.isPrimary!==!1){y.preventDefault(),d=y.pointerId,f={x:y.clientX,y:y.clientY},m=y.button===2,e.style.cursor="grabbing";try{y.target.setPointerCapture(y.pointerId)}catch{}i&&i.pauseOnInteraction!==!1&&(u=!0)}}function A(y){if(d===null||y.pointerId!==d||!o||a)return;y.preventDefault();let w=y.clientX-f.x,_=y.clientY-f.y;f={x:y.clientX,y:y.clientY};let T=s;if(m||y.shiftKey)g.rotY=g.rotY-w*L*T,g.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,g.rotX+_*L*T));else{let H=g.target;g.target=[H[0]-w*E/g.zoom,H[1]-_*E/g.zoom,H[2]]}n.rerender()}function M(y){if(d===y.pointerId){d=null,m=!1,e.style.cursor=o&&!a?"grab":"";try{y.target.releasePointerCapture(y.pointerId)}catch{}i&&(u=!1)}}function x(y){y.preventDefault()}function p(y){if(!r||a)return;y.preventDefault();let w=y.deltaY*.001;g.zoom=Math.max(.05,Math.min(10,g.zoom*(1-w))),n.rerender()}function b(y){if(!(a||!i)){if(!u){let w=h!==null?Math.min(y-h,50):16.67,_=typeof i=="object"&&i.speed?i.speed:.3,T=typeof i=="object"&&i.axis?i.axis:"y",H=_*(Math.PI/180)*(w/16.67);T==="y"?g.rotY=g.rotY+H:g.rotX=g.rotX+H,n.rerender()}h=y,c=requestAnimationFrame(b)}}function l(){c===null&&typeof requestAnimationFrame<"u"&&i&&(c=requestAnimationFrame(b))}function v(){c!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(c),c=null),h=null}function G(){e.addEventListener("pointerdown",S),e.addEventListener("pointermove",A),e.addEventListener("pointerup",M),e.addEventListener("pointercancel",M),e.addEventListener("contextmenu",x),e.addEventListener("wheel",p,{passive:!1}),e.style.cursor=o?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function C(){e.removeEventListener("pointerdown",S),e.removeEventListener("pointermove",A),e.removeEventListener("pointerup",M),e.removeEventListener("pointercancel",M),e.removeEventListener("contextmenu",x),e.removeEventListener("wheel",p),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return G(),l(),{update(y){let w=!!i;o=y.drag??o,r=y.wheel??r,s=Ne(y.invert),i=y.animate??i,!a&&d===null&&(e.style.cursor=o?"grab":"");let _=!!i;w&&!_?v():!w&&_&&l()},pause(){a||(a=!0,C(),v(),d=null,u=!1)},resume(){a&&(a=!1,G(),l())},destroy(){a||C(),v(),a=!0}}}function Ne(n){return n===void 0||n===!1?1:n===!0?-1:n}function vt(n,t={}){if(n.camera.kind!=="perspective")throw new Error("glyphcss: GlyphFirstPersonControls requires a perspective camera. Use <GlyphPerspectiveCamera> (not <GlyphOrthographicCamera> / <GlyphCamera>).");n.camera.eyeMode=!0;let e=n.host,o=t.drag??!0,r=t.keyboard??!0,s=t.moveSpeed??.05,i=t.lookSpeed??.004,a=Xe(t.invert),u=!1,c=null,h={x:0,y:0},d=new Set,f=null,m=n.camera;function g(l){if(!(!o||u)&&c===null){l.preventDefault(),c=l.pointerId,h={x:l.clientX,y:l.clientY};try{l.target.setPointerCapture(l.pointerId)}catch{}}}function L(l){if(c===null||l.pointerId!==c||!o||u)return;l.preventDefault();let v=l.clientX-h.x,G=l.clientY-h.y;h={x:l.clientX,y:l.clientY},m.rotY=m.rotY-v*i*a,m.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,m.rotX+G*i*a)),n.rerender()}function E(l){if(c===l.pointerId){c=null;try{l.target.releasePointerCapture(l.pointerId)}catch{}}}function S(l){r&&!u&&d.add(l.key.toLowerCase())}function A(l){d.delete(l.key.toLowerCase())}function M(){if(u||!r||d.size===0)return;let l=m.target,v=Math.cos(m.rotY),G=Math.sin(m.rotY),C=!1;(d.has("w")||d.has("arrowup"))&&(m.target=[l[0]-G*s,l[1]-v*s,l[2]],C=!0),(d.has("s")||d.has("arrowdown"))&&(m.target=[l[0]+G*s,l[1]+v*s,l[2]],C=!0),(d.has("a")||d.has("arrowleft"))&&(m.target=[l[0]-v*s,l[1]+G*s,l[2]],C=!0),(d.has("d")||d.has("arrowright"))&&(m.target=[l[0]+v*s,l[1]-G*s,l[2]],C=!0),C&&n.rerender()}function x(){u||(M(),f=requestAnimationFrame(x))}function p(){e.addEventListener("pointerdown",g),e.addEventListener("pointermove",L),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),r&&(e.ownerDocument?.addEventListener("keydown",S),e.ownerDocument?.addEventListener("keyup",A)),e.style.touchAction="none",e.style.userSelect="none",typeof requestAnimationFrame<"u"&&(f=requestAnimationFrame(x))}function b(){e.removeEventListener("pointerdown",g),e.removeEventListener("pointermove",L),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.ownerDocument?.removeEventListener("keydown",S),e.ownerDocument?.removeEventListener("keyup",A),e.style.touchAction="",e.style.userSelect="",f!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(f),f=null),d.clear(),n.camera.eyeMode=!1}return p(),{update(l){o=l.drag??o,r=l.keyboard??r,s=l.moveSpeed??s,i=l.lookSpeed??i,a=Xe(l.invert)},pause(){u||(u=!0,b(),c=null)},resume(){u&&(u=!1,p())},destroy(){u||b(),u=!0}}}function Xe(n){return n===void 0||n===!1?1:n===!0?-1:n}function Et(n,t){let e=n.querySelector(`[data-glyph-mesh-id="${CSS.escape(t)}"]`);return e instanceof HTMLElement?e:null}function Ve(n,t,e){let o=n.getBoundingClientRect();return o.width<=0||o.height<=0?!1:t>=o.left&&t<=o.right&&e>=o.top&&e<=o.bottom}function Gt(n,t,e){let o=(n instanceof Document,n),r=Array.from(o.querySelectorAll(".glyph-mesh"));for(let s of r)if(Ve(s,t,e))return s;return null}var Mt=typeof HTMLElement<"u"?HTMLElement:class{},Ct=["mode","glyph-palette","use-colors","cols","rows","cell-aspect","directional-direction","directional-intensity","ambient-intensity","auto-size"];function Z(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function xt(n){if(n==="wireframe"||n==="solid"||n==="voxel")return n}function At(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}var Ce=class extends Mt{constructor(){super(...arguments);this._scene=null}static get observedAttributes(){return[...Ct]}getScene(){return this._scene}_readOptions(){let e={},o=xt(this.getAttribute("mode"));o!==void 0&&(e.mode=o);let r=this.getAttribute("glyph-palette");r&&(e.glyphPalette=r);let s=At(this.getAttribute("use-colors"));s!==void 0&&(e.useColors=s);let i=Z(this.getAttribute("cols"));i!==void 0&&(e.cols=i);let a=Z(this.getAttribute("rows"));a!==void 0&&(e.rows=a);let u=Z(this.getAttribute("cell-aspect"));u!==void 0&&(e.cellAspect=u);let c=Z(this.getAttribute("directional-intensity"));c!==void 0&&(e.directionalLight={direction:[.5,.7,.5],intensity:c});let h=Z(this.getAttribute("ambient-intensity"));return h!==void 0&&(e.ambientLight={intensity:h}),this.hasAttribute("auto-size")&&(e.autoSize=!0),e}_findCameraAncestor(){let e=this.parentElement;for(;e;){let o=e.tagName.toLowerCase();if(o==="glyph-perspective-camera"||o==="glyph-orthographic-camera"||o==="glyph-camera")return e;e=e.parentElement}return null}_initScene(e){let o=typeof e.getCamera=="function"?e.getCamera():void 0,r=this._readOptions();o&&(r.camera=o),this._scene=Ee(this,r),this.dispatchEvent(new CustomEvent("glyphcss:scene-ready",{bubbles:!1}))}connectedCallback(){if(this._scene)return;let e=this._findCameraAncestor();if(!e)throw new Error("glyphcss: <glyph-scene> must be placed inside a <glyph-camera>, <glyph-perspective-camera>, or <glyph-orthographic-camera>.");if((typeof e.getCamera=="function"?e.getCamera():null)!==null)this._initScene(e);else{let r=()=>{e.removeEventListener("glyph:camera-ready",r),this._scene||this._initScene(e)};e.addEventListener("glyph:camera-ready",r)}}rerender(){this._scene?.rerender()}disconnectedCallback(){this._scene&&(this._scene.destroy(),this._scene=null)}attributeChangedCallback(e,o,r){o!==r&&this._scene&&this._scene.setOptions(this._readOptions())}};import{loadMesh as Lt,resolveGeometry as St,computeSceneBbox as wt}from"@glyphcss/core";var _t=typeof HTMLElement<"u"?HTMLElement:class{},Ht=["src","geometry","size","color","position","scale","rotation","normalize"];function Tt(n){let t=wt(n),e=(t.min[0]+t.max[0])/2,o=(t.min[1]+t.max[1])/2,r=(t.min[2]+t.max[2])/2,i=2/(Math.max(t.max[0]-t.min[0],t.max[1]-t.min[1],t.max[2]-t.min[2])||1);return n.map(a=>({...a,vertices:a.vertices.map(u=>[(u[0]-e)*i,(u[1]-o)*i,(u[2]-r)*i])}))}function xe(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function zt(n){if(n){if(!n.includes(",")){let t=parseFloat(n);return Number.isFinite(t)?t:void 0}return xe(n)}}function Pt(n){return n.closest("glyph-scene")??null}var Ae=class extends _t{constructor(){super(...arguments);this._handle=null;this._loadToken=0}static get observedAttributes(){return[...Ht]}getMeshHandle(){return this._handle}connectedCallback(){this._maybeLoad()}disconnectedCallback(){this._tearDown()}attributeChangedCallback(e,o,r){if(o!==r){if(e==="src"||e==="geometry"||e==="size"||e==="color"){this._tearDown(),this._maybeLoad();return}this._handle&&this._handle.setTransform(this._readTransform())}}_readTransform(){return{position:xe(this.getAttribute("position")),scale:zt(this.getAttribute("scale")),rotation:xe(this.getAttribute("rotation"))}}_tearDown(){if(this._loadToken+=1,this._handle){try{this._handle.dispose()}catch{}this._handle=null}}async _maybeLoad(){let e=this.getAttribute("src"),o=this.getAttribute("geometry"),r=Pt(this);if(r){if(!r.getScene()){let s=()=>{r.removeEventListener("glyphcss:scene-ready",s),this._maybeLoad()};r.addEventListener("glyphcss:scene-ready",s);return}if(e){let s=++this._loadToken,i;try{i=await Lt(e)}catch(h){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:h,bubbles:!0}));return}if(s!==this._loadToken){try{i.dispose()}catch{}return}let a=r.getScene();if(!a){try{i.dispose()}catch{}return}let c=this.hasAttribute("normalize")?Tt(i.polygons):i.polygons;this._handle=a.add(c,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{polygons:c},bubbles:!0}));return}if(o){let s=r.getScene();if(!s)return;let i=this.getAttribute("size"),a=i!==null?parseFloat(i):1,u=this.getAttribute("color")??void 0,c;try{c=St(o,{size:Number.isFinite(a)?a:1,color:u})}catch(h){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:h,bubbles:!0}));return}this._handle=s.add(c,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{polygons:c},bubbles:!0}))}}}};var Ot=typeof HTMLElement<"u"?HTMLElement:class{};function kt(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function Rt(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==2||t.some(e=>!Number.isFinite(e))))return[t[0],t[1]]}function It(n){return n.closest("glyph-scene")??null}var Le=class extends Ot{constructor(){super(...arguments);this._handle=null}static get observedAttributes(){return["at","size","hotspot-id"]}connectedCallback(){this._register()}disconnectedCallback(){this._handle&&this._unregister()}attributeChangedCallback(e,o,r){o!==r&&(this._handle&&this._unregister(),this._register())}_unregister(){if(!this._handle)return;let e=this._handle.el;for(;e.firstChild;)this.appendChild(e.firstChild);this._handle.remove(),this._handle=null}_register(){let e=kt(this.getAttribute("at"));if(!e)return;let o=It(this);if(!o)return;if(!o.getScene()){let u=()=>{o.removeEventListener("glyphcss:scene-ready",u),this._register()};o.addEventListener("glyphcss:scene-ready",u);return}let r=o.getScene();if(!r)return;let s=this.getAttribute("hotspot-id")??this.getAttribute("id")??String(Math.random()),i=Rt(this.getAttribute("size"));this._handle=r.addHotspot({id:s,at:e,size:i},()=>this.dispatchEvent(new CustomEvent("glyphcss:hotspot-click",{detail:{id:s},bubbles:!0})));let a=this._handle.el;for(;this.firstChild;)a.appendChild(this.firstChild)}};var Ft=typeof HTMLElement<"u"?HTMLElement:class{};function R(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}var Se=class extends Ft{constructor(){super(...arguments);this._camera=null}static get observedAttributes(){return["rot-x","rot-y","distance","zoom","stretch"]}getCamera(){return this._camera}connectedCallback(){this._camera=K({rotX:R(this.getAttribute("rot-x")),rotY:R(this.getAttribute("rot-y")),distance:R(this.getAttribute("distance")),zoom:R(this.getAttribute("zoom")),stretch:R(this.getAttribute("stretch"))}),this.dispatchEvent(new CustomEvent("glyph:camera-ready",{bubbles:!1}))}disconnectedCallback(){this._camera=null}attributeChangedCallback(e,o,r){if(o===r)return;let s=this._camera;if(!s)return;let i=R(this.getAttribute("rot-x")),a=R(this.getAttribute("rot-y")),u=R(this.getAttribute("distance")),c=R(this.getAttribute("zoom")),h=R(this.getAttribute("stretch")),d=!1;i!==void 0&&s.rotX!==i&&(s.rotX=i,d=!0),a!==void 0&&s.rotY!==a&&(s.rotY=a,d=!0),u!==void 0&&s.distance!==u&&(s.distance=u,d=!0),c!==void 0&&s.zoom!==c&&(s.zoom=c,d=!0),h!==void 0&&s.stretch!==h&&(s.stretch=h,d=!0),d&&this.querySelector("glyph-scene")?.rerender?.()}};var Yt=typeof HTMLElement<"u"?HTMLElement:class{};function W(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}var we=class extends Yt{constructor(){super(...arguments);this._camera=null}static get observedAttributes(){return["rot-x","rot-y","zoom"]}getCamera(){return this._camera}connectedCallback(){this._camera=ee({rotX:W(this.getAttribute("rot-x")),rotY:W(this.getAttribute("rot-y")),zoom:W(this.getAttribute("zoom"))}),this.dispatchEvent(new CustomEvent("glyph:camera-ready",{bubbles:!1}))}disconnectedCallback(){this._camera=null}attributeChangedCallback(e,o,r){if(o===r)return;let s=this._camera;if(!s)return;let i=W(this.getAttribute("rot-x")),a=W(this.getAttribute("rot-y")),u=W(this.getAttribute("zoom")),c=!1;i!==void 0&&s.rotX!==i&&(s.rotX=i,c=!0),a!==void 0&&s.rotY!==a&&(s.rotY=a,c=!0),u!==void 0&&s.zoom!==u&&(s.zoom=u,c=!0),c&&this.querySelector("glyph-scene")?.rerender?.()}};var Dt=typeof HTMLElement<"u"?HTMLElement:class{};function Nt(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function _e(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function Xt(n){return n.closest("glyph-scene")??null}var He=class extends Dt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert","animate-speed","animate-axis"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,o,r){o!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=_e(this.getAttribute("drag")),o=_e(this.getAttribute("wheel")),r=_e(this.getAttribute("invert")),s=Nt(this.getAttribute("animate-speed")),i=this.getAttribute("animate-axis")==="x"?"x":"y";return{...e!==void 0?{drag:e}:{},...o!==void 0?{wheel:o}:{},...r!==void 0?{invert:r}:{},...s!==void 0?{animate:{speed:s,axis:i}}:{}}}_attach(){if(this._controls)return;let e=Xt(this);if(!e)return;let o=e.getScene();if(!o){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=Ge(o,this._readOptions())}};var Vt=typeof HTMLElement<"u"?HTMLElement:class{};function Te(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function Bt(n){return n.closest("glyph-scene")??null}var ze=class extends Vt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,o,r){o!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=Te(this.getAttribute("drag")),o=Te(this.getAttribute("wheel")),r=Te(this.getAttribute("invert"));return{...e!==void 0?{drag:e}:{},...o!==void 0?{wheel:o}:{},...r!==void 0?{invert:r}:{}}}_attach(){if(this._controls)return;let e=Bt(this);if(!e)return;let o=e.getScene();if(!o){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=Me(o,this._readOptions())}};export*from"@glyphcss/core";export{it as DEFAULT_RAMP,Le as GlyphHotspotElement,ze as GlyphMapControlsElement,Ae as GlyphMeshElement,He as GlyphOrbitControlsElement,we as GlyphOrthographicCameraElement,Se as GlyphPerspectiveCameraElement,Ce as GlyphSceneElement,st as SOLID_RAMP,lt as WIREFRAME_GLYPHS,te as WIREFRAME_PALETTES,ht as bakeFrames,fe as buildRasterizeContext,tt as createGlyphCamera,vt as createGlyphFirstPersonControls,Me as createGlyphMapControls,Ge as createGlyphOrbitControls,ee as createGlyphOrthographicCamera,K as createGlyphPerspectiveCamera,Ee as createGlyphScene,Et as findGlyphMeshHandle,Gt as findMeshUnderPoint,ne as getWireframeGlyphs,be as injectGlyphBaseStyles,Ve as pointInMeshElement,ve as projectHotspots,re as rasterize};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glyphcss",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Glyphcss — ASCII paint backend with
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Glyphcss — ASCII paint backend with glyphcss's scene-composition API. Renders 3D meshes as ASCII art in a <pre> element.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@glyphcss/core": "^0.0.
|
|
36
|
+
"@glyphcss/core": "^0.0.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"tsup": "^8.0.1",
|