kireji 0.14.0 → 0.15.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/package.json +1 -1
- package/src/app/kireji/issue-tracker/sections/issues/1776205973/affects_.js +1 -1
- package/src/app/kireji/issue-tracker/sections/issues/1776205973/description +3 -3
- package/src/app/kireji/issue-tracker/sections/issues/1776205973/title +1 -1
- package/src/app/kireji/issue-tracker/sections/issues/1776206413/affects_.js +1 -1
- package/src/build.js +8 -0
- package/src/parts/abstract/part/model-reset.js +12 -0
- package/src/parts/abstract/part/model-set.js +4 -1
- package/src/parts/abstract/part/part.json +1 -0
- package/src/parts/abstract/part/type.d.ts +2 -0
- package/src/parts/abstract/scroller/onresize.js +1 -1
- package/src/parts/abstract/scroller/wrap.js +1 -1
- package/src/parts/abstract/type.d.ts +1 -1
- package/src/parts/abstract/{mesh → walkable}/build.js +12 -12
- package/src/parts/abstract/walkable/constants.js +1 -0
- package/src/parts/abstract/walkable/data-get.js +11 -0
- package/src/parts/abstract/walkable/description-abstract +1 -0
- package/src/parts/abstract/{mesh → walkable}/mathML-subpart.js +2 -2
- package/src/parts/abstract/walkable/model_.js +1 -0
- package/src/parts/abstract/{mesh → walkable}/point-tri-contains.js +1 -1
- package/src/parts/abstract/walkable/point-tri-that-contains.js +10 -0
- package/src/parts/abstract/{mesh → walkable}/ray-cast.js +17 -20
- package/src/parts/abstract/{mesh → walkable}/routeID-distribute.js +9 -9
- package/src/parts/abstract/{mesh → walkable}/routeID-model-to.js +2 -2
- package/src/parts/abstract/walkable/type.d.ts +109 -0
- package/src/parts/core/address-bar/async-install.js +1 -3
- package/src/parts/core/pointer/handle.js +3 -1
- package/src/parts/desktop/era/vintage/static.css +34 -5
- package/src/static.css +139 -1
- package/src/type.d.ts +56 -14
- package/src/parts/abstract/mesh/constants.js +0 -1
- package/src/parts/abstract/mesh/data-get.js +0 -11
- package/src/parts/abstract/mesh/model_.js +0 -1
- package/src/parts/abstract/mesh/point-tri-that-contains.js +0 -10
- package/src/parts/abstract/mesh/type.d.ts +0 -109
- /package/src/parts/abstract/{mesh → walkable}/part.json +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
There are four potential improvements that can be used to refine
|
|
1
|
+
There are four potential improvements that can be used to refine walkable raycasting to improve edge sliding and potentially performance (if necessary).
|
|
2
2
|
|
|
3
|
-
1. When the angle of the line through the opposing neighbors appears exactly straight, consider searching in a wider radius for asymmetry in the
|
|
4
|
-
2. Consider memoizing triangle neighbors and offering a NEIGHBORS_ONLY argument into the function that determines which triangle a given point falls on. This might improve raytracing performance but it might also introduce edge cases (for example, for
|
|
3
|
+
1. When the angle of the line through the opposing neighbors appears exactly straight, consider searching in a wider radius for asymmetry in the walkable boundary. This can help prevent dead stops when the force vector is exactly perpendicular to a straight portion of a very gently angled edge.
|
|
4
|
+
2. Consider memoizing triangle neighbors and offering a NEIGHBORS_ONLY argument into the function that determines which triangle a given point falls on. This might improve raytracing performance but it might also introduce edge cases (for example, for walkable with tris that are very thin slivers).
|
|
5
5
|
3. For accurate "friction", we should reduce the speed of the vector-to-nearest-boundary-neighbor proportionally to how far that vector deviates from true force vector.
|
|
6
6
|
4. When the ray casting time limit does not provide enough time to make a full diagonal move, consider moving to one of the two 4-point neighbors that sits between the current ray position and the target diagonal neighbor.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Refine
|
|
1
|
+
Refine Walkable Ray Casting
|
package/src/build.js
CHANGED
|
@@ -82,6 +82,12 @@ function ƒ(_, compressedSubjectOrigins) {
|
|
|
82
82
|
|
|
83
83
|
// Math Utilities
|
|
84
84
|
class Vector {
|
|
85
|
+
static 2(x = 0, y = 0) {
|
|
86
|
+
return { x, y }
|
|
87
|
+
}
|
|
88
|
+
static 3(x = 0, y = 0, z = 0) {
|
|
89
|
+
return { x, y, z }
|
|
90
|
+
}
|
|
85
91
|
static magnitude(vector) {
|
|
86
92
|
return Math.hypot(...Object.values(vector))
|
|
87
93
|
}
|
|
@@ -757,6 +763,8 @@ function ƒ(_, compressedSubjectOrigins) {
|
|
|
757
763
|
const constant = this
|
|
758
764
|
constant.path = SOURCE_PATH
|
|
759
765
|
constant.line = SOURCE_LINE
|
|
766
|
+
if (!constant.line.endsWith(";"))
|
|
767
|
+
constant.line += ";"
|
|
760
768
|
constant.lineNumber = SOURCE_LINE_NUMBER
|
|
761
769
|
constant.source = sourceFile.addSource(SOURCE_PATH, SOURCE_LINE)
|
|
762
770
|
constant.equalsIndex = SOURCE_LINE.indexOf("=")
|
|
@@ -68,6 +68,8 @@ declare interface IPart<TOwner, TSubpart>
|
|
|
68
68
|
readonly startBuild(): void
|
|
69
69
|
/** Performs `part.modelToRouteID()` on MODEL and then performs `part.setRouteID()` on the resulting route ID. */
|
|
70
70
|
readonly setModel(MODEL: any, SKIP_RUNTIME_STATE_DISTRIBUTION: boolean = false)
|
|
71
|
+
/** Sets the route ID on the part to match the landing model (or route ID 0n, if the part is not mentioned in the landing model). */
|
|
72
|
+
readonly resetModel(MODEL: any, SKIP_RUNTIME_STATE_DISTRIBUTION: boolean = false)
|
|
71
73
|
/** Sets the part's routeID, propagating it leafward and rootward and updating all views.
|
|
72
74
|
*
|
|
73
75
|
* If DELTA is true, ROUTE_ID is added to the part's current route ID.
|
|
@@ -2,7 +2,7 @@ scroller.onscroll()
|
|
|
2
2
|
const ratio = scroller.container.scrollHeight / scroller.container.clientHeight
|
|
3
3
|
const precisionFactor = 100_000
|
|
4
4
|
|
|
5
|
-
scroller.scrollBar.style.setProperty("--ratio", ratio)
|
|
5
|
+
scroller.scrollBar.style.setProperty("--scroll-thumb-ratio", ratio)
|
|
6
6
|
|
|
7
7
|
if (Math.round(ratio * precisionFactor) === precisionFactor)
|
|
8
8
|
scroller.scrollBar.setAttribute("disabled", "")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
return `<scroller-><scroll-content>${INNER_HTML}</scroll-content></scroller-><scroll-bar ${scroller.pointAttr("buttonPoint")} style="--fraction:${scroller.fraction};--ratio:1" disabled><button ${scroller.pointAttr("buttonPoint")} class=scroll-up></button><thumb- ${scroller.pointAttr("thumbPoint")}></thumb-><button ${scroller.pointAttr("buttonPoint")} class=scroll-down></button></scroll-bar>`
|
|
1
|
+
return `<scroller-><scroll-content>${INNER_HTML}</scroll-content></scroller-><scroll-bar ${scroller.pointAttr("buttonPoint")} style="--fraction:${scroller.fraction};--scroll-thumb-ratio:1" disabled><button ${scroller.pointAttr("buttonPoint")} class=scroll-up></button><thumb- ${scroller.pointAttr("thumbPoint")}></thumb-><button ${scroller.pointAttr("buttonPoint")} class=scroll-down></button></scroll-bar>`
|
|
@@ -11,7 +11,7 @@ declare interface IAbstract
|
|
|
11
11
|
readonly facet: IFacet<IAbstract, null>
|
|
12
12
|
readonly issue: ITrackedIssue<IAbstract>
|
|
13
13
|
readonly match: IMatch<IAbstract, null>
|
|
14
|
-
readonly
|
|
14
|
+
readonly walkable: IWalkable<IAbstract>
|
|
15
15
|
readonly mix: IMix<IAbstract, null>
|
|
16
16
|
readonly part: IPart<IAbstract, null>
|
|
17
17
|
readonly partMask: IPartMask<IAbstract, null>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
walkable.define({
|
|
2
2
|
triTable: { value: [] },
|
|
3
3
|
triIndex: { value: -1, writable: true },
|
|
4
|
-
position: { value:
|
|
4
|
+
position: { value: Vector[3]() },
|
|
5
5
|
data: {
|
|
6
6
|
resolve() {
|
|
7
|
-
return
|
|
7
|
+
return walkable.getData()
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
10
|
cardinality: {
|
|
11
11
|
resolve() {
|
|
12
|
-
let
|
|
12
|
+
let walkableCardinality = 0n
|
|
13
13
|
|
|
14
|
-
// Obtain the raw data for this
|
|
15
|
-
const [pointList, tris] = this.data.
|
|
14
|
+
// Obtain the raw data for this walkable.
|
|
15
|
+
const [pointList, tris] = this.data.walkable
|
|
16
16
|
|
|
17
17
|
// Iterate over each tri (array of three point indices) in the data.
|
|
18
18
|
for (const tri of tris) {
|
|
@@ -59,7 +59,7 @@ mesh.define({
|
|
|
59
59
|
// This row doesn't have a full pixel. Adjust the z-range.
|
|
60
60
|
if (z <= zRange.min + 1) zRange.min = z + 1
|
|
61
61
|
else if (z >= zRange.max - 1) zRange.max = z - 1
|
|
62
|
-
else throw new Error("Unexpected tri geometry found in
|
|
62
|
+
else throw new Error("Unexpected tri geometry found in walkable.")
|
|
63
63
|
continue
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -70,7 +70,7 @@ mesh.define({
|
|
|
70
70
|
min.x = Math.ceil(min.x)
|
|
71
71
|
max.x = Math.ceil(max.x) - 1
|
|
72
72
|
|
|
73
|
-
/** @type {
|
|
73
|
+
/** @type {IWalkableTriDataRow} */
|
|
74
74
|
const row = {
|
|
75
75
|
z,
|
|
76
76
|
xyRange: { min, max },
|
|
@@ -82,18 +82,18 @@ mesh.define({
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// Store the tri.
|
|
85
|
-
|
|
85
|
+
walkable.triTable.push({
|
|
86
86
|
points,
|
|
87
87
|
zRange,
|
|
88
88
|
rows,
|
|
89
|
-
offset:
|
|
89
|
+
offset: walkableCardinality,
|
|
90
90
|
cardinality: triCardinality
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
walkableCardinality += triCardinality
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
return
|
|
96
|
+
return walkableCardinality
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const walkable = this
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { points, tris } = walkable.manifest
|
|
2
|
+
|
|
3
|
+
const data = { walkable: [[], []] }
|
|
4
|
+
|
|
5
|
+
for (let index = 0; index < points.length; index += 2)
|
|
6
|
+
data.walkable[0].push([Math.round(points[index]), 0, Math.round(points[index + 1])])
|
|
7
|
+
|
|
8
|
+
for (let index = 0; index < tris.length; index += 3)
|
|
9
|
+
data.walkable[1].push([tris[index], tris[index + 1], tris[index + 2]])
|
|
10
|
+
|
|
11
|
+
return data
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This part represents a state space that is formed by quantizing the { x, z } positions of a 3D trianglated mesh. It is equipped with a per-frame ray-tracing method that uses a movement vector to handle the trade-off from triangle to triangle and converts route IDs to { x, y, z } coordinates. This is useful for for 2D and 3D games because it creates a state space that includes all of the positions a character is allowed to walk on and does not include any points that lie outside the mesh boundaries.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
if (DEPTH <= 0)
|
|
2
2
|
return [
|
|
3
|
-
`<munder><mo>∑</mo><mrow><mi>t</mi><mo>∈</mo><mi>tris</mi><mo>(</mo><msub><mi>𝑝</mi><mi>${
|
|
3
|
+
`<munder><mo>∑</mo><mrow><mi>t</mi><mo>∈</mo><mi>tris</mi><mo>(</mo><msub><mi>𝑝</mi><mi>${walkable.key}</mi></msub><mo>)</mo></mrow></munder>`,
|
|
4
4
|
`<munder><mo>∑</mo><mrow><mi>r</mi><mo>∈</mo><mi>rows</mi><mo>(</mo><mi>t</mi><mo>)</mo></mrow></munder>`,
|
|
5
5
|
`<msub><mi>𝑘</mi><mi>r</mi></msub>`
|
|
6
6
|
]
|
|
7
7
|
|
|
8
|
-
return /*
|
|
8
|
+
return /*walkable.triTable.length > 20 ? base(DEPTH) :*/ walkable.triTable.flatMap(triData => {
|
|
9
9
|
return [`<mn>${triData.cardinality}</mn>`, "<mo>+</mo>"]
|
|
10
10
|
}).slice(0, -1)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
return { ...walkable.position }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Check current tri first.
|
|
2
|
+
if (walkable.triIndex !== -1 && walkable.triContainsPoint(walkable.triIndex, POINT))
|
|
3
|
+
return walkable.triIndex
|
|
4
|
+
|
|
5
|
+
// Check all tris.
|
|
6
|
+
for (let triIndex = 0; triIndex < walkable.triTable.length; triIndex++)
|
|
7
|
+
if (triIndex !== walkable.triIndex && walkable.triContainsPoint(triIndex, POINT))
|
|
8
|
+
return triIndex
|
|
9
|
+
|
|
10
|
+
return -1
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Define a safe result: the current position before casting.
|
|
2
|
-
/** @type {
|
|
2
|
+
/** @type {IWalkableRayCastResult} */
|
|
3
3
|
const safeIterationResult = {
|
|
4
4
|
hit: false,
|
|
5
|
-
triIndex:
|
|
6
|
-
point:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
triIndex: walkable.triIndex,
|
|
6
|
+
point: Vector[3](
|
|
7
|
+
walkable.position.x,
|
|
8
|
+
0, // Exclude y coordinate from the ray casting algorithm for now.
|
|
9
|
+
walkable.position.z
|
|
10
|
+
),
|
|
11
11
|
forceVector: FORCE_VECTOR
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -18,7 +18,7 @@ const speed = Vector.magnitude(FORCE_VECTOR)
|
|
|
18
18
|
if (speed !== 0) {
|
|
19
19
|
|
|
20
20
|
// Initialize timing data as though the vector doesn't intersect any grid lines.
|
|
21
|
-
const timeOfNextIntersection =
|
|
21
|
+
const timeOfNextIntersection = Vector[3](Infinity, Infinity, Infinity)
|
|
22
22
|
const timeBetweenIntersections = { ...timeOfNextIntersection }
|
|
23
23
|
|
|
24
24
|
// Set the clock to zero.
|
|
@@ -62,7 +62,7 @@ if (speed !== 0) {
|
|
|
62
62
|
|
|
63
63
|
// Emergency exit the loop.
|
|
64
64
|
if (_.now - start >= 2000) {
|
|
65
|
-
warn("
|
|
65
|
+
warn("Walkable ray cast calculation exceeded the maximum allowable processing time of 2 seconds.", { processingTime: _.now - start, iteration, DELTA_TIME, FORCE_VECTOR, speed, safeIterationResult, timeOfNextIntersection, timeBetweenIntersections })
|
|
66
66
|
break castRay
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -94,8 +94,8 @@ if (speed !== 0) {
|
|
|
94
94
|
// Construct the next point along the ray, given the elapsed time.
|
|
95
95
|
const point = Vector.add(safeIterationResult.point, Vector.multiply(FORCE_VECTOR, timeElapsedDuringThisIteration))
|
|
96
96
|
|
|
97
|
-
// Check if the point is outside the
|
|
98
|
-
const triIndex =
|
|
97
|
+
// Check if the point is outside the walkable boundary.
|
|
98
|
+
const triIndex = walkable.triThatContainsPoint(point)
|
|
99
99
|
|
|
100
100
|
// If it is...
|
|
101
101
|
if (triIndex === -1) {
|
|
@@ -113,10 +113,7 @@ if (speed !== 0) {
|
|
|
113
113
|
dot: -Infinity,
|
|
114
114
|
point: null,
|
|
115
115
|
triIndex: null,
|
|
116
|
-
direction:
|
|
117
|
-
x: null,
|
|
118
|
-
z: null
|
|
119
|
-
}
|
|
116
|
+
direction: Vector[3](null, null, null)
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
let boundaryAppearsFlat = false
|
|
@@ -139,9 +136,9 @@ if (speed !== 0) {
|
|
|
139
136
|
|
|
140
137
|
// Get the position of the center of the neighbor.
|
|
141
138
|
const point = Vector.add(Vector.floor(Vector.add(safeIterationResult.point, direction)), 0.5)
|
|
142
|
-
const triIndex =
|
|
139
|
+
const triIndex = walkable.triThatContainsPoint(point)
|
|
143
140
|
|
|
144
|
-
// If it isn't part of the
|
|
141
|
+
// If it isn't part of the walkable, exclude it from consideration.
|
|
145
142
|
if (triIndex === -1)
|
|
146
143
|
continue
|
|
147
144
|
|
|
@@ -199,7 +196,7 @@ if (speed !== 0) {
|
|
|
199
196
|
|
|
200
197
|
// Construct the point along the way to the neighbor.
|
|
201
198
|
const point = Vector.add(safeIterationResult.point, Vector.multiply(forceVectorToNeighbor, timeElapsedDuringThisIteration))
|
|
202
|
-
const triIndex =
|
|
199
|
+
const triIndex = walkable.triThatContainsPoint(point)
|
|
203
200
|
safeIterationResult.forceVector = forceVectorToNeighbor
|
|
204
201
|
|
|
205
202
|
if (triIndex === -1) {
|
|
@@ -265,8 +262,8 @@ if (speed !== 0) {
|
|
|
265
262
|
}
|
|
266
263
|
}
|
|
267
264
|
|
|
268
|
-
// Interpolate the y position of the
|
|
269
|
-
const triData =
|
|
265
|
+
// Interpolate the y position of the walkable at the given { x, y } coordinates.
|
|
266
|
+
const triData = walkable.triTable[safeIterationResult.triIndex]
|
|
270
267
|
const flooredZ = Math.floor(safeIterationResult.point.z)
|
|
271
268
|
const row = triData.rows[flooredZ - triData.zRange.min]
|
|
272
269
|
const t = (safeIterationResult.point.x - row.xyRange.min.x) / Number(row.cardinality)
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
walkable.updateRouteID(ROUTE_ID)
|
|
2
2
|
|
|
3
3
|
if (SKIP_RUNTIME_STATE_DISTRIBUTION)
|
|
4
4
|
return
|
|
5
5
|
|
|
6
6
|
// Binary search better than embedded match.
|
|
7
|
-
|
|
7
|
+
walkable.triIndex = (() => {
|
|
8
8
|
|
|
9
9
|
let low = 0
|
|
10
|
-
let high =
|
|
10
|
+
let high = walkable.triTable.length - 1
|
|
11
11
|
|
|
12
12
|
while (low <= high) {
|
|
13
13
|
|
|
14
14
|
const mid = (low + high) >>> 1
|
|
15
|
-
const triData =
|
|
16
|
-
const nextTriData =
|
|
15
|
+
const triData = walkable.triTable[mid]
|
|
16
|
+
const nextTriData = walkable.triTable[mid + 1]
|
|
17
17
|
|
|
18
18
|
if (ROUTE_ID < triData.offset)
|
|
19
19
|
high = mid - 1
|
|
@@ -27,10 +27,10 @@ mesh.triIndex = (() => {
|
|
|
27
27
|
return 0
|
|
28
28
|
})()
|
|
29
29
|
|
|
30
|
-
ROUTE_ID -=
|
|
30
|
+
ROUTE_ID -= walkable.triTable[walkable.triIndex].offset
|
|
31
31
|
|
|
32
32
|
// Embedded match can become binary search later.
|
|
33
|
-
for (const row of
|
|
33
|
+
for (const row of walkable.triTable[walkable.triIndex].rows) {
|
|
34
34
|
|
|
35
35
|
if (!row)
|
|
36
36
|
continue
|
|
@@ -38,8 +38,8 @@ for (const row of mesh.triTable[mesh.triIndex].rows) {
|
|
|
38
38
|
const rowWidth = BigInt(row.xyRange.max.x - row.xyRange.min.x + 1)
|
|
39
39
|
|
|
40
40
|
if (ROUTE_ID < row.offset + rowWidth) {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
walkable.position.x = row.xyRange.min.x + Number(ROUTE_ID - row.offset)
|
|
42
|
+
walkable.position.z = row.z
|
|
43
43
|
break
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const triIndex =
|
|
2
|
-
const triData =
|
|
1
|
+
const triIndex = walkable.triThatContainsPoint(MODEL)
|
|
2
|
+
const triData = walkable.triTable[triIndex]
|
|
3
3
|
const row = triData.rows[Math.floor(MODEL.z) - triData.zRange.min]
|
|
4
4
|
return triData.offset + row.offset + BigInt(Math.floor(MODEL.x) - row.xyRange.min.x)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
declare interface IWalkable<TOwner>
|
|
2
|
+
extends IPart<TOwner, null> {
|
|
3
|
+
|
|
4
|
+
// Serialized Properties.
|
|
5
|
+
readonly getData(): IWalkableData
|
|
6
|
+
/** Casts a ray from the current walkable position along the force vector direction for the given delta time and returns a summary of the results. @param FORCE_VECTOR the force vector represent the position the uninterrupted ray will arrive at in one second. @param DELTA_TIME the duration of the time cast in seconds. @param ENABLE_SLIDING whether or not to enable the ray to "wrap" along the walkable boundary instead of stopping cold. */
|
|
7
|
+
readonly castRay(FORCE_VECTOR: IVector3, DELTA_TIME: number, ENABLE_SLIDING: boolean): IWalkableRayCastResult
|
|
8
|
+
/** Checks if a point (x, y, z) rounds to a valid pixel within the specified tri's memoized row data. */
|
|
9
|
+
readonly triContainsPoint(TRI_INDEX: IWalkableTriIndex, POINT: IVector3): boolean
|
|
10
|
+
/** Returns whether or not the given point is in a tri. @returns the index of the tri that contains the point. -1 otherwise. */
|
|
11
|
+
readonly triThatContainsPoint(POINT: IVector3): IWalkableTriIndex
|
|
12
|
+
|
|
13
|
+
// Runtime Properties.
|
|
14
|
+
/** The memoization data of every tri in the walkable, stored by tri index at build-time. */
|
|
15
|
+
readonly triTable: IWalkableTriData[]
|
|
16
|
+
/** The index of the current tri in the walkable. */
|
|
17
|
+
readonly triIndex?: IWalkableTriIndex
|
|
18
|
+
/** The current position of the state in the walkable. */
|
|
19
|
+
readonly position: IVector3
|
|
20
|
+
readonly manifest: IWalkableManifest
|
|
21
|
+
/** A cache of the pre-processed geometry data obtained by running the getData method. */
|
|
22
|
+
readonly data: IWalkableData
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare interface IWalkableRayCastResult {
|
|
26
|
+
/** Whether or not the ray hit the walkable boundary. */
|
|
27
|
+
readonly hit: boolean
|
|
28
|
+
/** The tri the ray most recently occupied when it hit the boundary or the index of the boundary where the ray stopped if there is no hit. */
|
|
29
|
+
readonly triIndex: IWalkableTriIndex
|
|
30
|
+
/** The rounded cell position where the cast ray landed. */
|
|
31
|
+
readonly point: IVector3
|
|
32
|
+
/** The force vector used to cast the ray, which might be different from the input if sliding is enabled as it may point along the direction of the most recent sliding iteration. */
|
|
33
|
+
readonly forceVector: IVector3
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare interface IWalkableTriData {
|
|
37
|
+
/** The original point array of the tri as taken from `walkable.getData()`. */
|
|
38
|
+
readonly points: IWalkableTriPoints
|
|
39
|
+
/** The z-axis range of the tri. */
|
|
40
|
+
readonly zRange: {
|
|
41
|
+
/** The z position of the top-most row of the tri. */
|
|
42
|
+
readonly min: number
|
|
43
|
+
/** The z position of the bottom-most row of the tri. */
|
|
44
|
+
readonly max: number
|
|
45
|
+
}
|
|
46
|
+
/** The rows of pixels in the tri. */
|
|
47
|
+
readonly rows: IWalkableTriDataRow[]
|
|
48
|
+
/** The offset of the tri in the overall walkable. */
|
|
49
|
+
readonly offset: bigint
|
|
50
|
+
/** The total number of pixels in the tri. */
|
|
51
|
+
readonly cardinality: bigint
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
declare interface IWalkableTriDataRow {
|
|
55
|
+
/** The z position of this row of the tri's space. */
|
|
56
|
+
readonly z: number
|
|
57
|
+
/** The x-axis range of the row stored with the corresponding y-axis coordinate at those two points. */
|
|
58
|
+
readonly xyRange: {
|
|
59
|
+
/** The smallest x position that is within the tri row. */
|
|
60
|
+
readonly min: {
|
|
61
|
+
readonly x: number,
|
|
62
|
+
readonly y: number
|
|
63
|
+
}
|
|
64
|
+
/** The largest x position that is within the tri row. */
|
|
65
|
+
readonly max: {
|
|
66
|
+
readonly x: number,
|
|
67
|
+
readonly y: number
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** The bigint offset of this row in the overall tri. */
|
|
71
|
+
readonly offset: bigint
|
|
72
|
+
/** The number of points in the given row. */
|
|
73
|
+
readonly cardinality: bigint
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
declare interface IWalkableManifest
|
|
78
|
+
extends IPartManifest {
|
|
79
|
+
/** The available walkable vertices as a flat array of 2D coordinates. Used for defining the world's walkable tris. */
|
|
80
|
+
readonly points: number[],
|
|
81
|
+
/** The list of walkable triangles, as a flat array of point triples. Used to define the walkable area of the world. */
|
|
82
|
+
readonly tris: number[]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare type IWalkableData = {
|
|
86
|
+
readonly walkable: [IWalkablePoint[], IWalkableTri[]]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
declare type IWalkableTri =
|
|
90
|
+
[IWalkablePointIndex, IWalkablePointIndex, IWalkablePointIndex]
|
|
91
|
+
|
|
92
|
+
declare type IWalkablePointIndex =
|
|
93
|
+
number
|
|
94
|
+
|
|
95
|
+
declare type IWalkableTriPoints =
|
|
96
|
+
[IWalkablePoint, IWalkablePoint, IWalkablePoint]
|
|
97
|
+
|
|
98
|
+
declare type IWalkablePoint =
|
|
99
|
+
[x: number, y: number, z: number]
|
|
100
|
+
|
|
101
|
+
declare type IWalkableTriIndex =
|
|
102
|
+
number
|
|
103
|
+
|
|
104
|
+
declare type IWalkableAny =
|
|
105
|
+
IWalkable<IPartAny>
|
|
106
|
+
|
|
107
|
+
declare const walkable: IWalkableAny
|
|
108
|
+
|
|
109
|
+
declare const TRI: IWalkableTriData
|
|
@@ -94,9 +94,11 @@ const
|
|
|
94
94
|
document.addEventListener("pointermove", drag, { capture: true, signal: controller.signal })
|
|
95
95
|
document.addEventListener("pointerup", drop, { capture: true, signal: controller.signal })
|
|
96
96
|
document.addEventListener("pointercancel", reset, { capture: true, signal: controller.signal })
|
|
97
|
+
pointer.id = POINTER_CONFIG.POINTER_EVENT.pointerId
|
|
97
98
|
|
|
98
99
|
// Don't allow anything else to start picking up events.
|
|
99
|
-
|
|
100
|
+
if (!document.pointerLockElement)
|
|
101
|
+
POINTER_CONFIG.TARGET_ELEMENT.setPointerCapture(pointer.id)
|
|
100
102
|
|
|
101
103
|
// Allow CSS styles to target the element while its down.
|
|
102
104
|
POINTER_CONFIG.TARGET_ELEMENT.classList.add("down")
|
|
@@ -6,6 +6,40 @@ html {
|
|
|
6
6
|
linear-gradient(45deg, var(--bg) 25%, transparent 25%, transparent 75%, var(--bg) 75%, var(--bg)) 1px 1px / 2px 2px;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
wallpaper->* {
|
|
10
|
+
--deep-inset-dpx:
|
|
11
|
+
inset var(--d-1px) var(--d-1px) var(--bg-light-est),
|
|
12
|
+
inset var(--d1px) var(--d1px) var(--bg-dark),
|
|
13
|
+
inset var(--d-2px) var(--d-2px) var(--bg-light-er),
|
|
14
|
+
inset var(--d2px) var(--d2px) black;
|
|
15
|
+
--deep-outset-dpx:
|
|
16
|
+
inset var(--d-1px) var(--d-1px) black,
|
|
17
|
+
inset var(--d1px) var(--d1px) var(--bg-light-er),
|
|
18
|
+
inset var(--d-2px) var(--d-2px) var(--bg-dark),
|
|
19
|
+
inset var(--d2px) var(--d2px) var(--bg-light-est);
|
|
20
|
+
--bg-checker-dpx-color: var(--bg);
|
|
21
|
+
--bg-checker-dpx:
|
|
22
|
+
linear-gradient(45deg, var(--bg-checker-dpx-color) 25%, transparent 25%, transparent 75%, var(--bg-checker-dpx-color) 75%, var(--bg-checker-dpx-color)) 0 0 / var(--d2px) var(--d2px),
|
|
23
|
+
linear-gradient(45deg, var(--bg-checker-dpx-color) 25%, transparent 25%, transparent 75%, var(--bg-checker-dpx-color) 75%, var(--bg-checker-dpx-color)) var(--d1px) var(--d1px) / var(--d2px) var(--d2px);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
body.dark wallpaper->* {
|
|
27
|
+
--deep-inset-dpx:
|
|
28
|
+
inset var(--d-1px) var(--d-1px) var(--bg-light-est),
|
|
29
|
+
inset var(--d1px) var(--d1px) var(--bg-dark),
|
|
30
|
+
inset var(--d-2px) var(--d-2px) var(--bg-light-er),
|
|
31
|
+
inset var(--d2px) var(--d2px) black;
|
|
32
|
+
--deep-outset-dpx:
|
|
33
|
+
inset var(--d-1px) var(--d-1px) black,
|
|
34
|
+
inset var(--d1px) var(--d1px) var(--bg-light),
|
|
35
|
+
inset var(--d-2px) var(--d-2px) var(--bg-dark),
|
|
36
|
+
inset var(--d2px) var(--d2px) var(--bg-light-er);
|
|
37
|
+
--bg-checker-dpx-color: var(--bg);
|
|
38
|
+
--bg-checker-dpx:
|
|
39
|
+
linear-gradient(45deg, var(--bg-checker-dpx-color) 25%, transparent 25%, transparent 75%, var(--bg-checker-dpx-color) 75%, var(--bg-checker-dpx-color)) 0 0 / var(--d2px) var(--d2px),
|
|
40
|
+
linear-gradient(45deg, var(--bg-checker-dpx-color) 25%, transparent 25%, transparent 75%, var(--bg-checker-dpx-color) 75%, var(--bg-checker-dpx-color)) var(--d1px) var(--d1px) / var(--d2px) var(--d2px);
|
|
41
|
+
}
|
|
42
|
+
|
|
9
43
|
scroll-bar {
|
|
10
44
|
background: var(--bg-checker), white;
|
|
11
45
|
}
|
|
@@ -197,11 +231,6 @@ task-bar {
|
|
|
197
231
|
}
|
|
198
232
|
|
|
199
233
|
body.dark {
|
|
200
|
-
--deep-inset:
|
|
201
|
-
inset -1px -1px var(--bg-light-est),
|
|
202
|
-
inset 1px 1px var(--bg-dark),
|
|
203
|
-
inset -2px -2px var(--bg-light-er),
|
|
204
|
-
inset 2px 2px black;
|
|
205
234
|
--deep-outset:
|
|
206
235
|
inset -1px -1px black,
|
|
207
236
|
inset 1px 1px var(--bg-light),
|
package/src/static.css
CHANGED
|
@@ -47,6 +47,30 @@ body {
|
|
|
47
47
|
-ms-user-select: none;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
html {
|
|
51
|
+
/* Default safe fallback (1x screens or older browsers) */
|
|
52
|
+
--dppx: 1;
|
|
53
|
+
--css-length-of-device-pixel: calc(1px / var(--dppx));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media (min-resolution: 2dppx) {
|
|
57
|
+
html {
|
|
58
|
+
--dppx: 2;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (min-resolution: 3dppx) {
|
|
63
|
+
html {
|
|
64
|
+
--dppx: 3;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@media (min-resolution: 4dppx) {
|
|
69
|
+
html {
|
|
70
|
+
--dppx: 4;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
50
74
|
wallpaper- {
|
|
51
75
|
--app-height: var(--wallpaper-height);
|
|
52
76
|
--app-width: var(--wallpaper-width);
|
|
@@ -58,6 +82,120 @@ wallpaper- {
|
|
|
58
82
|
overflow: hidden;
|
|
59
83
|
overflow: clip;
|
|
60
84
|
touch-action: manipulation;
|
|
85
|
+
container-type: size;
|
|
86
|
+
container-name: design;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@container design (aspect-ratio >1 / 1) {
|
|
90
|
+
|
|
91
|
+
wallpaper->* {
|
|
92
|
+
--design-tiles-along-app-width: 16;
|
|
93
|
+
--design-tiles-along-app-height: 9;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@container design (aspect-ratio <=1 / 1) {
|
|
98
|
+
|
|
99
|
+
wallpaper->* {
|
|
100
|
+
--design-tiles-along-app-width: 9;
|
|
101
|
+
--design-tiles-along-app-height: 16;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
wallpaper->* {
|
|
106
|
+
|
|
107
|
+
/* UI Design based on a simple 16 x 9 or 9 x 16 square layout,
|
|
108
|
+
with each tile having this many "design pixels". */
|
|
109
|
+
--design-pixels-per-tile: 20;
|
|
110
|
+
|
|
111
|
+
--design-pixels-along-app-width:
|
|
112
|
+
calc(var(--design-tiles-along-app-width) * var(--design-pixels-per-tile));
|
|
113
|
+
|
|
114
|
+
--design-pixels-along-app-height:
|
|
115
|
+
calc(var(--design-tiles-along-app-height) * var(--design-pixels-per-tile));
|
|
116
|
+
|
|
117
|
+
--css-length-of-design-pixel-if-using-app-width:
|
|
118
|
+
calc(var(--app-width) / var(--design-pixels-along-app-width));
|
|
119
|
+
|
|
120
|
+
--css-length-of-design-pixel-if-using-app-height:
|
|
121
|
+
calc(var(--app-height) / var(--design-pixels-along-app-height));
|
|
122
|
+
|
|
123
|
+
--css-length-of-design-pixel:
|
|
124
|
+
min(var(--css-length-of-design-pixel-if-using-app-width), var(--css-length-of-design-pixel-if-using-app-height));
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
/* Now, round the design pixel down to align the pixel art to
|
|
128
|
+
the user device's physical screen pixels. */
|
|
129
|
+
--design-pixel:
|
|
130
|
+
max(var(--css-length-of-device-pixel), round(down, var(--css-length-of-design-pixel), var(--css-length-of-device-pixel)));
|
|
131
|
+
|
|
132
|
+
/* Now, we can define the actual size of the design area in CSS pixels. */
|
|
133
|
+
--ui-width: calc(var(--d1px) * var(--design-pixels-along-app-width));
|
|
134
|
+
--ui-height: calc(var(--d1px) * var(--design-pixels-along-app-height));
|
|
135
|
+
|
|
136
|
+
/* The design area is likely smaller than the actual container,
|
|
137
|
+
so we determine the offset needed to center it. */
|
|
138
|
+
--ui-left: calc((var(--app-width) - var(--ui-width)) / 2);
|
|
139
|
+
--ui-top: calc((var(--app-height) - var(--ui-height)) / 2);
|
|
140
|
+
|
|
141
|
+
/* Add some shortcuts to common design pixel amounts. */
|
|
142
|
+
--d1px: calc(1 * var(--design-pixel));
|
|
143
|
+
--d2px: calc(2 * var(--d1px));
|
|
144
|
+
--d3px: calc(3 * var(--d1px));
|
|
145
|
+
--d4px: calc(4 * var(--d1px));
|
|
146
|
+
--d5px: calc(5 * var(--d1px));
|
|
147
|
+
--d6px: calc(6 * var(--d1px));
|
|
148
|
+
--d7px: calc(7 * var(--d1px));
|
|
149
|
+
--d8px: calc(8 * var(--d1px));
|
|
150
|
+
--d16px: calc(16 * var(--d1px));
|
|
151
|
+
--d-1px: calc(-1 * var(--d1px));
|
|
152
|
+
--d-2px: calc(-2 * var(--d1px));
|
|
153
|
+
--d-3px: calc(-3 * var(--d1px));
|
|
154
|
+
--d-4px: calc(-4 * var(--d1px));
|
|
155
|
+
--d-5px: calc(-5 * var(--d1px));
|
|
156
|
+
--d-6px: calc(-6 * var(--d1px));
|
|
157
|
+
--d-7px: calc(-7 * var(--d1px));
|
|
158
|
+
--d-8px: calc(-8 * var(--d1px));
|
|
159
|
+
--d-16px: calc(-16 * var(--d1px));
|
|
160
|
+
|
|
161
|
+
/* Compute the scalar ratio between a CSS pixel and a design pixel. */
|
|
162
|
+
--design-scale: calc(var(--d1px) / 1px);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@property --ui-width {
|
|
166
|
+
syntax: "<length>";
|
|
167
|
+
initial-value: 0px;
|
|
168
|
+
inherits: true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@property --ui-height {
|
|
172
|
+
syntax: "<length>";
|
|
173
|
+
initial-value: 0px;
|
|
174
|
+
inherits: true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@property --ui-left {
|
|
178
|
+
syntax: "<length>";
|
|
179
|
+
initial-value: 0px;
|
|
180
|
+
inherits: true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@property --ui-top {
|
|
184
|
+
syntax: "<length>";
|
|
185
|
+
initial-value: 0px;
|
|
186
|
+
inherits: true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@property --d1px {
|
|
190
|
+
syntax: "<length>";
|
|
191
|
+
initial-value: 0px;
|
|
192
|
+
inherits: true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
wallpaper->* {
|
|
196
|
+
/* Cross-platform bug fix for Firefox's inability
|
|
197
|
+
to divide two values if both have units. */
|
|
198
|
+
--design-scale: calc(10000 * tan(atan2(var(--d1px), 10000px))) !important;
|
|
61
199
|
}
|
|
62
200
|
|
|
63
201
|
@media (width < 640px) {
|
|
@@ -136,7 +274,7 @@ scroll-bar>:is(.scroll-up, thumb-, .scroll-down) {
|
|
|
136
274
|
|
|
137
275
|
scroll-bar>thumb- {
|
|
138
276
|
top: calc(var(--thumb-start) + var(--track-height) * var(--fraction));
|
|
139
|
-
height: calc(var(--track-height) / var(--
|
|
277
|
+
height: calc(var(--track-height) / var(--design-scale));
|
|
140
278
|
}
|
|
141
279
|
|
|
142
280
|
body:not(.unhydrated) scroller- {
|
package/src/type.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ declare interface IEcosystem
|
|
|
56
56
|
/** The hash of the desired landing page, as computed from data parameters during the initial boot process. */
|
|
57
57
|
readonly landingHash: string
|
|
58
58
|
/** The model of the desired landing page, used during the initial boot process to compute `_.landingHash` and `_.landingRouteID`. */
|
|
59
|
-
readonly landingModel:
|
|
59
|
+
readonly landingModel: object
|
|
60
60
|
/** The routeID of the desired landing page, as computed from data parameters during the initial boot process. */
|
|
61
61
|
readonly landingRouteID: bigint
|
|
62
62
|
/** A boolean that is set to `true` as soon as the route ID is set for the first time. */
|
|
@@ -398,21 +398,63 @@ declare class FenwickTree {
|
|
|
398
398
|
}
|
|
399
399
|
/** A utility class for handling arbitrary-length vectors. Any object with entirely numeric values can be treated as a vector. */
|
|
400
400
|
declare class Vector {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
static
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
static
|
|
409
|
-
/**
|
|
410
|
-
static
|
|
411
|
-
/**
|
|
412
|
-
static
|
|
413
|
-
|
|
401
|
+
|
|
402
|
+
/** Creates the vector object `{ x, y }`. */
|
|
403
|
+
static 2(x: number = 0, y: number = 0): IVector2
|
|
404
|
+
/** Creates the vector object `{ x: 0, y: 0, z: 0 }`. */
|
|
405
|
+
static 3(x: number = 0, y: number = 0, z: number = 0): IVector3
|
|
406
|
+
|
|
407
|
+
/** Provides the absolute value (length) of the the given vector. Returns a number. */
|
|
408
|
+
static magnitude<TVector extends IVector>(vector: TVector): number
|
|
409
|
+
/** Normalizes the given vector so that its magnitude is exactly 1. Returns a vector of the same dimension. */
|
|
410
|
+
static normalize<TVector extends IVector>(vector: TVector): TVector
|
|
411
|
+
/** Returns the sign of the given vector. Returns a vector of the same dimension. */
|
|
412
|
+
static sign<TVector extends IVector>(vector: TVector): TVector
|
|
413
|
+
/** Returns a vector of the same dimension with all components floored. */
|
|
414
|
+
static floor<TVector extends IVector>(vector: TVector): TVector
|
|
415
|
+
|
|
416
|
+
/** Performs the given binary operation on vector a and number b. Returns a vector of the same dimension as vector a. */
|
|
417
|
+
static operate<TVector extends IVector>(a: TVector, b: number, operation: TOperation): TVector
|
|
418
|
+
/** Performs the given binary operation on number a and vector b. Returns a vector of the same dimension as vector b. */
|
|
419
|
+
static operate<TVector extends IVector>(a: number, b: TVector, operation: TOperation): TVector
|
|
420
|
+
/** Performs the given binary operation on vectors a and b. They must have the same dimension. Returns a vector of the same dimension. */
|
|
421
|
+
static operate<TVector extends IVector>(a: TVector, b: TVector, operation: TOperation): TVector
|
|
422
|
+
/** Performs the given binary operation on numbers a and b. Returns a number. */
|
|
423
|
+
static operate(a: number, b: number, operation: TOperation): number
|
|
424
|
+
|
|
425
|
+
/** Adds vector a to number b. Returns a vector of the same dimension as vector a. */
|
|
426
|
+
static add<TVector extends IVector>(a: TVector, b: number): TVector
|
|
427
|
+
/** Adds number a to bector b. Returns a vector of the same dimension as vector b. */
|
|
428
|
+
static add<TVector extends IVector>(a: number, b: TVector): TVector
|
|
429
|
+
/** Adds vectors a to b. They must have the same dimension. Returns a vector of the same dimension. */
|
|
430
|
+
static add<TVector extends IVector>(a: TVector, b: TVector): TVector
|
|
431
|
+
/** Adds numbers a to b. Returns a number. */
|
|
432
|
+
static add(a: number, b: number): number
|
|
433
|
+
|
|
434
|
+
/** Subtracts number b from vector a. Returns a vector of the same dimension as vector a. */
|
|
435
|
+
static subtract<TVector extends IVector>(a: TVector, b: number): TVector
|
|
436
|
+
/** Subtracts vector b from number a. Returns a vector of the same dimension as vector b. */
|
|
437
|
+
static subtract<TVector extends IVector>(a: number, b: TVector): TVector
|
|
438
|
+
/** Subtracts vector b from vector a. They must have the same dimension. Returns a vector of the same dimension. */
|
|
439
|
+
static subtract<TVector extends IVector>(a: TVector, b: TVector): TVector
|
|
440
|
+
/** Subtracts number b from number a. Returns a number. */
|
|
441
|
+
static subtract(a: number, b: number): number
|
|
442
|
+
|
|
443
|
+
/** Multiplies vector a by number b. Returns a vector of the same dimension as vector a. */
|
|
444
|
+
static multiply<TVector extends IVector>(a: TVector, b: number): TVector
|
|
445
|
+
/** Multiplies number a by bector b. Returns a vector of the same dimension as vector b. */
|
|
446
|
+
static multiply<TVector extends IVector>(a: number, b: TVector): TVector
|
|
447
|
+
/** Multiplies vectors a and b. They must have the same dimension. Returns a vector of the same dimension. */
|
|
448
|
+
static multiply<TVector extends IVector>(a: TVector, b: TVector): TVector
|
|
449
|
+
/** Multiplies numbers a and b. Returns a number. */
|
|
450
|
+
static multiply(a: number, b: number): number
|
|
451
|
+
|
|
452
|
+
/** Returns the dot product of the two vectors. The vectors must have the same dimension. Returns a number. */
|
|
453
|
+
static dot<TVector>(vector1: TVector, vector2: TVector): number
|
|
414
454
|
}
|
|
415
455
|
|
|
456
|
+
declare type TOperation = (a: number, b: number) => number
|
|
457
|
+
|
|
416
458
|
declare type IVector = Record<string, number>
|
|
417
459
|
declare type IVector2 = { x: number, y: number }
|
|
418
460
|
declare type IVector3 = { x: number, y: number, z: number }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const mesh = this
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const { points, tris } = mesh.manifest
|
|
2
|
-
|
|
3
|
-
const data = { collision: [[], []] }
|
|
4
|
-
|
|
5
|
-
for (let index = 0; index < points.length; index += 2)
|
|
6
|
-
data.collision[0].push([Math.round(points[index]), 0, Math.round(points[index + 1])])
|
|
7
|
-
|
|
8
|
-
for (let index = 0; index < tris.length; index += 3)
|
|
9
|
-
data.collision[1].push([tris[index], tris[index + 1], tris[index + 2]])
|
|
10
|
-
|
|
11
|
-
return data
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
return { ...mesh.position }
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Check current tri first.
|
|
2
|
-
if (mesh.triIndex !== -1 && mesh.triContainsPoint(mesh.triIndex, POINT))
|
|
3
|
-
return mesh.triIndex
|
|
4
|
-
|
|
5
|
-
// Check all tris.
|
|
6
|
-
for (let triIndex = 0; triIndex < mesh.triTable.length; triIndex++)
|
|
7
|
-
if (triIndex !== mesh.triIndex && mesh.triContainsPoint(triIndex, POINT))
|
|
8
|
-
return triIndex
|
|
9
|
-
|
|
10
|
-
return -1
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
declare interface IMesh<TOwner>
|
|
2
|
-
extends IPart<TOwner, null> {
|
|
3
|
-
|
|
4
|
-
// Serialized Properties.
|
|
5
|
-
readonly getData(): IMeshData
|
|
6
|
-
/** Casts a ray from the current mesh position along the force vector direction for the given delta time and returns a summary of the results. @param FORCE_VECTOR the force vector represent the position the uninterrupted ray will arrive at in one second. @param DELTA_TIME the duration of the time cast in seconds. @param ENABLE_SLIDING whether or not to enable the ray to "wrap" along the mesh boundary instead of stopping cold. */
|
|
7
|
-
readonly castRay(FORCE_VECTOR: IVector3, DELTA_TIME: number, ENABLE_SLIDING: boolean): IMeshRayCastResult
|
|
8
|
-
/** Checks if a point (x, y, z) rounds to a valid pixel within the specified tri's memoized row data. */
|
|
9
|
-
readonly triContainsPoint(TRI_INDEX: IMeshTriIndex, POINT: IVector3): boolean
|
|
10
|
-
/** Returns whether or not the given point is in a tri. @returns the index of the tri that contains the point. -1 otherwise. */
|
|
11
|
-
readonly triThatContainsPoint(POINT: IVector3): IMeshTriIndex
|
|
12
|
-
|
|
13
|
-
// Runtime Properties.
|
|
14
|
-
/** The memoization data of every tri in the mesh, stored by tri index at build-time. */
|
|
15
|
-
readonly triTable: IMeshTriData[]
|
|
16
|
-
/** The index of the current tri in the mesh. */
|
|
17
|
-
readonly triIndex?: IMeshTriIndex
|
|
18
|
-
/** The current position of the state in the mesh. */
|
|
19
|
-
readonly position: IVector3
|
|
20
|
-
readonly manifest: IMeshManifest
|
|
21
|
-
/** A cache of the pre-processed geometry data obtained by running the getData method. */
|
|
22
|
-
readonly data: IMeshData
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
declare interface IMeshRayCastResult {
|
|
26
|
-
/** Whether or not the ray hit the mesh boundary. */
|
|
27
|
-
readonly hit: boolean
|
|
28
|
-
/** The tri the ray most recently occupied when it hit the boundary or the index of the boundary where the ray stopped if there is no hit. */
|
|
29
|
-
readonly triIndex: IMeshTriIndex
|
|
30
|
-
/** The rounded cell position where the cast ray landed. */
|
|
31
|
-
readonly point: IVector3
|
|
32
|
-
/** The force vector used to cast the ray, which might be different from the input if sliding is enabled as it may point along the direction of the most recent sliding iteration. */
|
|
33
|
-
readonly forceVector: IVector3
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
declare interface IMeshTriData {
|
|
37
|
-
/** The original point array of the tri as taken from `mesh.getData()`. */
|
|
38
|
-
readonly points: IMeshTriPoints
|
|
39
|
-
/** The z-axis range of the tri. */
|
|
40
|
-
readonly zRange: {
|
|
41
|
-
/** The z position of the top-most row of the tri. */
|
|
42
|
-
readonly min: number
|
|
43
|
-
/** The z position of the bottom-most row of the tri. */
|
|
44
|
-
readonly max: number
|
|
45
|
-
}
|
|
46
|
-
/** The rows of pixels in the tri. */
|
|
47
|
-
readonly rows: IMeshTriDataRow[]
|
|
48
|
-
/** The offset of the tri in the overall mesh. */
|
|
49
|
-
readonly offset: bigint
|
|
50
|
-
/** The total number of pixels in the tri. */
|
|
51
|
-
readonly cardinality: bigint
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
declare interface IMeshTriDataRow {
|
|
55
|
-
/** The z position of this row of the tri's space. */
|
|
56
|
-
readonly z: number
|
|
57
|
-
/** The x-axis range of the row stored with the corresponding y-axis coordinate at those two points. */
|
|
58
|
-
readonly xyRange: {
|
|
59
|
-
/** The smallest x position that is within the tri row. */
|
|
60
|
-
readonly min: {
|
|
61
|
-
readonly x: number,
|
|
62
|
-
readonly y: number
|
|
63
|
-
}
|
|
64
|
-
/** The largest x position that is within the tri row. */
|
|
65
|
-
readonly max: {
|
|
66
|
-
readonly x: number,
|
|
67
|
-
readonly y: number
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/** The bigint offset of this row in the overall tri. */
|
|
71
|
-
readonly offset: bigint
|
|
72
|
-
/** The number of points in the given row. */
|
|
73
|
-
readonly cardinality: bigint
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
declare interface IMeshManifest
|
|
78
|
-
extends IPartManifest {
|
|
79
|
-
/** The available collision vertices as a flat array of 2D coordinates. Used for defining the world's collision tris. */
|
|
80
|
-
readonly points: number[],
|
|
81
|
-
/** The list of collision tris, as a flat array of point triples. Used to define the walkable area of the world. */
|
|
82
|
-
readonly tris: number[]
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
declare type IMeshData = {
|
|
86
|
-
readonly collision: [IMeshPoint[], IMeshTri[]]
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
declare type IMeshTri =
|
|
90
|
-
[IMeshPointIndex, IMeshPointIndex, IMeshPointIndex]
|
|
91
|
-
|
|
92
|
-
declare type IMeshPointIndex =
|
|
93
|
-
number
|
|
94
|
-
|
|
95
|
-
declare type IMeshTriPoints =
|
|
96
|
-
[IMeshPoint, IMeshPoint, IMeshPoint]
|
|
97
|
-
|
|
98
|
-
declare type IMeshPoint =
|
|
99
|
-
[x: number, y: number, z: number]
|
|
100
|
-
|
|
101
|
-
declare type IMeshTriIndex =
|
|
102
|
-
number
|
|
103
|
-
|
|
104
|
-
declare type IMeshAny =
|
|
105
|
-
IMesh<IPartAny>
|
|
106
|
-
|
|
107
|
-
declare const mesh: IMeshAny
|
|
108
|
-
|
|
109
|
-
declare const TRI: IMeshTriData
|
|
File without changes
|