@solidrt/2d 0.0.70 → 0.0.72
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/AGENTS.md +222 -40
- package/README.md +7 -3
- package/examples/README.md +1 -1
- package/examples/camera-probe.tsx +4 -4
- package/examples/markers.tsx +3 -3
- package/package.json +5 -4
- package/src/animation.ts +26 -5
- package/src/atlas.ts +8 -4
- package/src/camera.ts +2 -2
- package/src/components/camera2d.tsx +2 -2
- package/src/components/group.tsx +15 -3
- package/src/components/shots.tsx +2 -2
- package/src/components/sprite-layer.tsx +40 -12
- package/src/components/sprite.tsx +31 -3
- package/src/components/text2d.tsx +2 -2
- package/src/components/tile-layer.tsx +21 -7
- package/src/components/view2d.tsx +2 -2
- package/src/dispatch.ts +10 -6
- package/src/frames.ts +1 -1
- package/src/glsl.ts +399 -0
- package/src/index.ts +14 -6
- package/src/layer.ts +260 -113
- package/src/material.ts +368 -0
- package/src/records.ts +198 -104
- package/src/style.ts +98 -0
- package/src/text.ts +64 -11
- package/src/tiles.ts +119 -24
- package/src/views.ts +17 -9
- package/src/shaders.ts +0 -323
package/src/components/group.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
2
2
|
import type { ParentComponent } from "@solidrt/core"
|
|
3
|
-
import { addGroup, destroyGroup, setGroup, setGroupTransition } from "../layer.ts"
|
|
3
|
+
import { addGroup, destroyGroup, setGroup, setGroupTimeScale, setGroupTransition } from "../layer.ts"
|
|
4
4
|
import type { SpriteGroup, TransitionEndEvent } from "../layer.ts"
|
|
5
5
|
import type { SpriteTransition } from "../layer.ts"
|
|
6
6
|
import { GroupContext, LayerContext } from "./context.ts"
|
|
@@ -24,6 +24,10 @@ export type GroupProps = BubblingSpritePointerProps & {
|
|
|
24
24
|
transition?: SpriteTransition | string | null
|
|
25
25
|
/** A declared transition settled on one component. */
|
|
26
26
|
onTransitionEnd?: (event: TransitionEndEvent) => void
|
|
27
|
+
/** The rate the native motion under this group runs at (see
|
|
28
|
+
* setGroupTimeScale): 0 freezes the subtree, 1 is app time; the nearest
|
|
29
|
+
* declaring node wins. Undefined or null inherits. */
|
|
30
|
+
timeScale?: number | null
|
|
27
31
|
ref?: (group: SpriteGroup) => void
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -47,6 +51,14 @@ export let Group: ParentComponent<GroupProps> = props => {
|
|
|
47
51
|
() => props.transition,
|
|
48
52
|
transition => setGroupTransition(group, transition ?? null),
|
|
49
53
|
)
|
|
54
|
+
// Built only when the prop is present (the compiler emits the getter
|
|
55
|
+
// only then), so a plain group pays no effect for it.
|
|
56
|
+
if ("timeScale" in props) {
|
|
57
|
+
createEffect(
|
|
58
|
+
() => props.timeScale,
|
|
59
|
+
scale => setGroupTimeScale(group, scale ?? null),
|
|
60
|
+
)
|
|
61
|
+
}
|
|
50
62
|
createEffect(
|
|
51
63
|
() => [props.onPointerDown, props.onPointerMove, props.onPointerUp, props.onPointerCancel, props.onWheel, props.onTap, props.onTransitionEnd] as const,
|
|
52
64
|
([down, move, up, cancel, wheel, tap, end]) => {
|
|
@@ -59,7 +71,7 @@ export let Group: ParentComponent<GroupProps> = props => {
|
|
|
59
71
|
group.onTransitionEnd = end
|
|
60
72
|
},
|
|
61
73
|
)
|
|
62
|
-
|
|
74
|
+
callRef(() => props.ref, group)
|
|
63
75
|
onCleanup(() => destroyGroup(group))
|
|
64
76
|
return <GroupContext value={group}>{props.children}</GroupContext>
|
|
65
77
|
}
|
package/src/components/shots.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, createEffect, onCleanup, onFrame, untrack, useContext } from "@solidrt/core"
|
|
1
|
+
import { callRef, createContext, createEffect, onCleanup, onFrame, untrack, useContext } from "@solidrt/core"
|
|
2
2
|
import type { Element, ParentComponent } from "@solidrt/core"
|
|
3
3
|
import { ViewportContext, useSpriteLayer } from "./context.ts"
|
|
4
4
|
import { createShots } from "../shots.ts"
|
|
@@ -59,7 +59,7 @@ export let Shots: ParentComponent<ShotsProps> = props => {
|
|
|
59
59
|
})
|
|
60
60
|
},
|
|
61
61
|
)
|
|
62
|
-
|
|
62
|
+
callRef(() => props.ref, shots)
|
|
63
63
|
return <ShotsContext value={shots}>{props.children}</ShotsContext>
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createEffect, displayScale, getBoundingBoxViewport, getLayoutBox, onCleanup, onLayout, untrack, warnOnce } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, displayScale, getBoundingBoxViewport, getLayoutBox, onCleanup, onLayout, untrack, warnOnce } from "@solidrt/core"
|
|
2
2
|
import type { Element, ParentComponent, PointerFeed, TextureId } from "@solidrt/core"
|
|
3
|
-
import type {
|
|
3
|
+
import type { ShaderParams } from "@solidrt/core/gpu"
|
|
4
4
|
import type { Atlas } from "../atlas.ts"
|
|
5
|
+
import type { Material } from "../material.ts"
|
|
5
6
|
import { createSpriteLayer } from "../layer.ts"
|
|
6
7
|
import { feedPointer } from "../views.ts"
|
|
7
8
|
import type { LayerPointerEvent, LayerTapEvent, LayerWheelEvent, SpriteLayer as LayerHandle } from "../layer.ts"
|
|
@@ -52,16 +53,22 @@ export type SpriteLayerProps = LayerPointerProps & {
|
|
|
52
53
|
* still its own, `<Sprite>`, `<Group>` and `<Text2d>` children mount
|
|
53
54
|
* into it - and leaves its lifetime to its maker, so the component
|
|
54
55
|
* face sits over an imperative layer. The creation props (atlases,
|
|
55
|
-
* capacity,
|
|
56
|
-
* with `layer` they have nothing to apply to and throw.
|
|
56
|
+
* capacity, material, orderBy) describe a layer the component makes,
|
|
57
|
+
* so with `layer` they have nothing to apply to and throw.
|
|
57
58
|
*/
|
|
58
59
|
layer?: LayerHandle
|
|
59
60
|
/** Initial record reservation (grows on demand); default 1024. */
|
|
60
61
|
capacity?: number
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* additive particles. Fixed at mount. */
|
|
64
|
-
|
|
62
|
+
/** The layer's material (see SpriteLayerOptions.material): its blend,
|
|
63
|
+
* its look, its per-sprite style record; default `unlit()`, `unlit({
|
|
64
|
+
* blend: "add" })` for glows and additive particles. Fixed at mount. */
|
|
65
|
+
material?: Material
|
|
66
|
+
/** Uniform values written to every view of the layer (layer.setParams
|
|
67
|
+
* as a prop, over the material's own): the material's prelude
|
|
68
|
+
* uniforms. Live, with merge semantics - a key that disappears keeps
|
|
69
|
+
* its last value; for per-frame values prefer `ref` + setParams from
|
|
70
|
+
* onFrame. */
|
|
71
|
+
params?: ShaderParams
|
|
65
72
|
/** The own view's clear color. */
|
|
66
73
|
clearColor?: [number, number, number, number]
|
|
67
74
|
/** Pan/zoom/rotate the own view over the world (in-shader); a
|
|
@@ -106,6 +113,13 @@ export type SpriteLayerProps = LayerPointerProps & {
|
|
|
106
113
|
* under it). Live: a change applies to the next frame's cascade.
|
|
107
114
|
*/
|
|
108
115
|
stagger?: number
|
|
116
|
+
/**
|
|
117
|
+
* The rate the layer's native motion runs at (layer.setTimeScale as a
|
|
118
|
+
* prop): 0 pauses every sprite and group transition while the app's UI
|
|
119
|
+
* keeps moving, 1 is app time; a `<Group timeScale={1}>` inside keeps
|
|
120
|
+
* running. Undefined or null is app time. Live.
|
|
121
|
+
*/
|
|
122
|
+
timeScale?: number | null
|
|
109
123
|
label?: string
|
|
110
124
|
/** The layer: sprites, tint, pick, createView. */
|
|
111
125
|
ref?: (layer: LayerHandle) => void
|
|
@@ -150,7 +164,7 @@ const FILL_INITIAL_SIZE = 1
|
|
|
150
164
|
|
|
151
165
|
// The props that describe a layer the component creates - meaningless,
|
|
152
166
|
// hence rejected, on an adopted one (`layer`), which was created already.
|
|
153
|
-
const CREATION_PROPS = ["atlases", "capacity", "
|
|
167
|
+
const CREATION_PROPS = ["atlases", "capacity", "material", "orderBy"] as const
|
|
154
168
|
|
|
155
169
|
// The props that configure the layer's own view - meaningless, hence
|
|
156
170
|
// rejected, on a layer without one (output={false}).
|
|
@@ -195,10 +209,12 @@ export let SpriteLayer: ParentComponent<SpriteLayerProps> = props => {
|
|
|
195
209
|
if (props.atlases === undefined) throw new Error("SpriteLayer: give atlases (a layer of its own) or layer (an existing one)")
|
|
196
210
|
return createSpriteLayer(props.atlases, {
|
|
197
211
|
capacity: props.capacity,
|
|
198
|
-
|
|
212
|
+
material: props.material,
|
|
213
|
+
params: props.params,
|
|
199
214
|
tint: props.tint,
|
|
200
215
|
orderBy: props.orderBy,
|
|
201
216
|
stagger: props.stagger,
|
|
217
|
+
timeScale: props.timeScale ?? undefined,
|
|
202
218
|
label: props.label,
|
|
203
219
|
})
|
|
204
220
|
})
|
|
@@ -208,12 +224,24 @@ export let SpriteLayer: ParentComponent<SpriteLayerProps> = props => {
|
|
|
208
224
|
if (tint !== undefined) layer.setTint(tint)
|
|
209
225
|
},
|
|
210
226
|
)
|
|
227
|
+
createEffect(
|
|
228
|
+
() => props.params,
|
|
229
|
+
params => {
|
|
230
|
+
if (params !== undefined) layer.setParams(params)
|
|
231
|
+
},
|
|
232
|
+
{ defer: true },
|
|
233
|
+
)
|
|
211
234
|
createEffect(
|
|
212
235
|
() => props.stagger,
|
|
213
236
|
ms => layer.setStagger(ms ?? null),
|
|
214
237
|
{ defer: true },
|
|
215
238
|
)
|
|
216
|
-
|
|
239
|
+
createEffect(
|
|
240
|
+
() => props.timeScale,
|
|
241
|
+
scale => layer.setTimeScale(scale ?? null),
|
|
242
|
+
{ defer: true },
|
|
243
|
+
)
|
|
244
|
+
callRef(() => props.ref, layer)
|
|
217
245
|
let output = untrack(() => props.output)
|
|
218
246
|
if (output === false) {
|
|
219
247
|
untrack(() => {
|
|
@@ -274,7 +302,7 @@ export let SpriteLayer: ParentComponent<SpriteLayerProps> = props => {
|
|
|
274
302
|
},
|
|
275
303
|
{ defer: true },
|
|
276
304
|
)
|
|
277
|
-
|
|
305
|
+
callRef(() => props.viewRef, view)
|
|
278
306
|
let pointer = untrack(() => props.pointer) ?? null
|
|
279
307
|
if (pointer) onCleanup(feedPointer(view, pointer))
|
|
280
308
|
// The view's own handlers at the root of the walk; the props are read
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
2
2
|
import type { VoidComponent } from "@solidrt/core"
|
|
3
|
-
import { addSprite, destroySprite, setSprite, setSpriteTransition } from "../layer.ts"
|
|
3
|
+
import { addSprite, destroySprite, setSprite, setSpriteTimeScale, setSpriteTransition } from "../layer.ts"
|
|
4
|
+
import { setInstanceStyle } from "../records.ts"
|
|
4
5
|
import type { Sprite as SpriteHandle, SpriteOptions, SpritePointerEvent, SpriteTapEvent, SpriteWheelEvent, TransitionEndEvent } from "../layer.ts"
|
|
5
6
|
import type { SpriteTransition } from "../layer.ts"
|
|
6
7
|
import { GroupContext, LayerContext } from "./context.ts"
|
|
@@ -43,6 +44,16 @@ export type SpriteProps = SpriteOptions &
|
|
|
43
44
|
transition?: SpriteTransition | string | null
|
|
44
45
|
/** A declared transition settled on one component. */
|
|
45
46
|
onTransitionEnd?: (event: TransitionEndEvent) => void
|
|
47
|
+
/** The rate this sprite's native motion runs at (see
|
|
48
|
+
* setSpriteTimeScale): 0 freezes it, 1 is app time, overriding the
|
|
49
|
+
* layer's and the enclosing groups'. Undefined or null inherits. Node
|
|
50
|
+
* layers only. */
|
|
51
|
+
timeScale?: number | null
|
|
52
|
+
/** The sprite's style record under the layer's material (see
|
|
53
|
+
* setInstanceStyle): one value per component of the material's first
|
|
54
|
+
* instance buffer. Absent, the sprite keeps the material's
|
|
55
|
+
* instanceStyle. */
|
|
56
|
+
style?: ArrayLike<number>
|
|
46
57
|
ref?: (sprite: SpriteHandle) => void
|
|
47
58
|
}
|
|
48
59
|
|
|
@@ -62,6 +73,23 @@ export let Sprite: VoidComponent<SpriteProps> = props => {
|
|
|
62
73
|
() => props.transition,
|
|
63
74
|
transition => setSpriteTransition(sprite, transition ?? null),
|
|
64
75
|
)
|
|
76
|
+
// Built only when the prop is present (the compiler emits the getter
|
|
77
|
+
// only then): a plain sprite pays no effect, and a record layer's
|
|
78
|
+
// sprite never meets the throw.
|
|
79
|
+
if ("timeScale" in props) {
|
|
80
|
+
createEffect(
|
|
81
|
+
() => props.timeScale,
|
|
82
|
+
scale => setSpriteTimeScale(sprite, scale ?? null),
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
if ("style" in props) {
|
|
86
|
+
createEffect(
|
|
87
|
+
() => props.style,
|
|
88
|
+
style => {
|
|
89
|
+
if (style !== undefined) setInstanceStyle(layer, sprite, style)
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
}
|
|
65
93
|
createEffect(
|
|
66
94
|
() => [props.onPointerDown, props.onPointerMove, props.onPointerUp, props.onPointerCancel, props.onPointerEnter, props.onPointerLeave, props.onWheel, props.onTap, props.onTransitionEnd] as const,
|
|
67
95
|
([down, move, up, cancel, enter, leave, wheel, tap, end]) => {
|
|
@@ -76,7 +104,7 @@ export let Sprite: VoidComponent<SpriteProps> = props => {
|
|
|
76
104
|
sprite.onTransitionEnd = end
|
|
77
105
|
},
|
|
78
106
|
)
|
|
79
|
-
|
|
107
|
+
callRef(() => props.ref, sprite)
|
|
80
108
|
onCleanup(() => destroySprite(sprite))
|
|
81
109
|
return null
|
|
82
110
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, onCleanup, untrack, useContext } from "@solidrt/core"
|
|
2
2
|
import type { VoidComponent } from "@solidrt/core"
|
|
3
3
|
import { setGroupTransition } from "../layer.ts"
|
|
4
4
|
import type { SpritePointerEvent, SpriteTapEvent, SpriteTransition, SpriteWheelEvent, TransitionEndEvent } from "../layer.ts"
|
|
@@ -71,7 +71,7 @@ export let Text2d: VoidComponent<Text2dProps> = props => {
|
|
|
71
71
|
run.group.onTransitionEnd = end
|
|
72
72
|
},
|
|
73
73
|
)
|
|
74
|
-
|
|
74
|
+
callRef(() => props.ref, run)
|
|
75
75
|
onCleanup(() => destroyText(run))
|
|
76
76
|
return null
|
|
77
77
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createEffect, createSignal, displayScale, For, getBoundingBoxViewport, onLayout, untrack } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, createSignal, displayScale, For, getBoundingBoxViewport, onLayout, untrack } from "@solidrt/core"
|
|
2
2
|
import type { VoidComponent } from "@solidrt/core"
|
|
3
|
-
import type {
|
|
3
|
+
import type { FilterMode, ShaderParams } from "@solidrt/core/gpu"
|
|
4
4
|
import type { Atlas } from "../atlas.ts"
|
|
5
|
+
import type { Material } from "../material.ts"
|
|
5
6
|
import type { CameraUpdate } from "../camera.ts"
|
|
6
7
|
import type { Frame } from "../frames.ts"
|
|
7
8
|
import { tileWorldScale } from "../oversample-math.ts"
|
|
@@ -35,9 +36,14 @@ export type TileLayerProps = {
|
|
|
35
36
|
* have no chunk and render nothing, so a full-bleed ground color belongs
|
|
36
37
|
* on the container behind the layer). */
|
|
37
38
|
chunkClearColor?: [number, number, number, number]
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
|
|
39
|
+
/** The material the cells bake with (see TileLayerOptions.material):
|
|
40
|
+
* its blend, its look, its per-cell style record; default `unlit()`.
|
|
41
|
+
* Fixed at mount. */
|
|
42
|
+
material?: Material
|
|
43
|
+
/** Uniform values written to every resident chunk (layer.setParams as
|
|
44
|
+
* a prop, over the material's own). Live, merge semantics; each change
|
|
45
|
+
* re-bakes every resident chunk - slow state, not per frame. */
|
|
46
|
+
params?: ShaderParams
|
|
41
47
|
/** Sampler filter for the baked chunk textures at composite time; default
|
|
42
48
|
* "linear" (hard pixels belong to the atlas sampler, see TileLayerOptions). */
|
|
43
49
|
filter?: FilterMode
|
|
@@ -88,7 +94,8 @@ export let TileLayer: VoidComponent<TileLayerProps> = props => {
|
|
|
88
94
|
let layer = untrack(() =>
|
|
89
95
|
createTileLayer(props.cols, props.rows, props.tileW, props.tileH, props.atlases, {
|
|
90
96
|
chunkClearColor: props.chunkClearColor,
|
|
91
|
-
|
|
97
|
+
material: props.material,
|
|
98
|
+
params: props.params,
|
|
92
99
|
filter: props.filter,
|
|
93
100
|
chunkTiles: props.chunkTiles,
|
|
94
101
|
tint: props.tint,
|
|
@@ -96,7 +103,7 @@ export let TileLayer: VoidComponent<TileLayerProps> = props => {
|
|
|
96
103
|
label: props.label,
|
|
97
104
|
}),
|
|
98
105
|
)
|
|
99
|
-
|
|
106
|
+
callRef(() => props.ref, layer)
|
|
100
107
|
createEffect(
|
|
101
108
|
() => props.oversample,
|
|
102
109
|
n => {
|
|
@@ -109,6 +116,13 @@ export let TileLayer: VoidComponent<TileLayerProps> = props => {
|
|
|
109
116
|
if (tint !== undefined) layer.setTint(tint)
|
|
110
117
|
},
|
|
111
118
|
)
|
|
119
|
+
createEffect(
|
|
120
|
+
() => props.params,
|
|
121
|
+
params => {
|
|
122
|
+
if (params !== undefined) layer.setParams(params)
|
|
123
|
+
},
|
|
124
|
+
{ defer: true },
|
|
125
|
+
)
|
|
112
126
|
// Auto oversample: the world view's window box, in device pixels, per
|
|
113
127
|
// world pixel. Rotation is not a resolution factor - texels per world
|
|
114
128
|
// pixel do not change as the camera turns - but the measured box is the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEffect, displayScale, getBoundingBoxViewport, onCleanup, onLayout, untrack, useContext } from "@solidrt/core"
|
|
1
|
+
import { callRef, createEffect, displayScale, getBoundingBoxViewport, onCleanup, onLayout, untrack, useContext } from "@solidrt/core"
|
|
2
2
|
import type { Element, ParentComponent, PointerFeed, TextureId } from "@solidrt/core"
|
|
3
3
|
import type { CameraUpdate } from "../camera.ts"
|
|
4
4
|
import { feedPointer } from "../views.ts"
|
|
@@ -96,7 +96,7 @@ export let View2d: ParentComponent<View2dProps> = props => {
|
|
|
96
96
|
},
|
|
97
97
|
{ defer: true },
|
|
98
98
|
)
|
|
99
|
-
|
|
99
|
+
callRef(() => props.ref, view)
|
|
100
100
|
onCleanup(() => view.dispose())
|
|
101
101
|
let pointer = untrack(() => props.pointer) ?? null
|
|
102
102
|
if (pointer) onCleanup(feedPointer(view, pointer))
|
package/src/dispatch.ts
CHANGED
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
// drag from empty space keeps delivering to the layer as it crosses
|
|
13
13
|
// sprites, exactly as a drag from a sprite keeps naming that sprite.
|
|
14
14
|
// Enter/leave pair on the sprite alone. Taps are synthesized here (DOM's
|
|
15
|
-
// click, Unity's IPointerClickHandler
|
|
16
|
-
//
|
|
17
|
-
//
|
|
15
|
+
// click, which is primary-button only; Unity's IPointerClickHandler fires
|
|
16
|
+
// for every button and reports it, we do not): a primary-button press
|
|
17
|
+
// that releases on the same target within the slop, the only pointer
|
|
18
|
+
// down for its whole press, counted up for repeats (DOM's detail,
|
|
19
|
+
// Unity's clickCount).
|
|
18
20
|
//
|
|
19
21
|
// Pure BY DESIGN (types and camera.ts, nothing with GPU imports) so
|
|
20
22
|
// tests/dispatch.test.ts drives it headless with a fake pick.
|
|
@@ -197,9 +199,11 @@ export function spriteDispatch(deps: DispatchDeps): (layout: (() => { width: num
|
|
|
197
199
|
}
|
|
198
200
|
presses.delete(e.pointerId)
|
|
199
201
|
walk("onPointerUp", makeEvent(press.target, x, y, e), !press.claimed)
|
|
200
|
-
// The tap rule:
|
|
201
|
-
// press
|
|
202
|
-
//
|
|
202
|
+
// The tap rule: the primary button (DOM click; core's press and
|
|
203
|
+
// long-press gate the same way), no travel past the slop, alone
|
|
204
|
+
// for the whole press, released over the target it pressed (empty
|
|
205
|
+
// space for the layer itself).
|
|
206
|
+
if (e.button != null && e.button !== 0) return
|
|
203
207
|
if (press.moved || !press.alone || topmost(x, y) !== press.target) return
|
|
204
208
|
let time = e.timeStamp
|
|
205
209
|
let repeat =
|
package/src/frames.ts
CHANGED
|
@@ -95,7 +95,7 @@ function frameOf(atlas: Atlas, x: number, y: number, w: number, h: number): Fram
|
|
|
95
95
|
* a cell and an animation is a slice of consecutive indices.
|
|
96
96
|
*
|
|
97
97
|
* Cells that touch do not bleed at mip level 0: the layer shaders clamp
|
|
98
|
-
* every sample into its frame (
|
|
98
|
+
* every sample into its frame (glsl.ts). A mip chain is different - its
|
|
99
99
|
* texels straddle cell edges before sampling - so a sheet going through
|
|
100
100
|
* `createAtlas` with `mipmap` is extruded first (`extrudeGrid`, whose
|
|
101
101
|
* returned options slice the repacked sheet).
|