spoint 0.1.674 → 0.1.675
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/client/BrowserServer.js +5 -1
- package/client/app.js +20 -0
- package/client/core/RenderGraph.js +19 -10
- package/client/core/RenderGraph.nodes.js +7 -0
- package/package.json +1 -1
- package/src/apps/AppLoader.js +1 -1
package/client/BrowserServer.js
CHANGED
|
@@ -227,8 +227,12 @@ export class BrowserServer extends BaseClient {
|
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
// Matches relative ('./x', '../x') AND root-absolute ('/x') import specifiers: the gh-pages deploy's
|
|
231
|
+
// path-patch step (gh-pages.yml "Patch paths for gh-pages") absolutizes deep relative src imports
|
|
232
|
+
// (apps/**/*.js climbing out via '../../src/...') into '/spoint/src/...' at build time, so a shipped
|
|
233
|
+
// app's own source can carry either form depending on how many directories deep it lives.
|
|
230
234
|
async function _resolveRelativeDeps(source, baseUrl, seen = new Map()) {
|
|
231
|
-
const re = /(?:from|import)\s*['"](\.[^'"]+)['"]/g
|
|
235
|
+
const re = /(?:from|import)\s*['"](\.[^'"]+|\/[^'"]+)['"]/g
|
|
232
236
|
const out = {}
|
|
233
237
|
const tasks = []
|
|
234
238
|
let m
|
package/client/app.js
CHANGED
|
@@ -2753,6 +2753,10 @@ function buildFrameSectionNodes() {
|
|
|
2753
2753
|
{
|
|
2754
2754
|
id: 'frame-clock',
|
|
2755
2755
|
reads: [], writes: ['frameDt', 'isEditorFrame', 'lerpFactor', 'localId'],
|
|
2756
|
+
// lerpFactor is a debug mirror (inspectable via window.__renderGraph) with no downstream graph
|
|
2757
|
+
// reader by design; frameDt/isEditorFrame/localId ARE read elsewhere, so only lerpFactor is
|
|
2758
|
+
// exempt here, not the whole node.
|
|
2759
|
+
debugMirrors: ['lerpFactor'],
|
|
2756
2760
|
run(ctx) {
|
|
2757
2761
|
const now = ctx.now
|
|
2758
2762
|
ctx.res.frameDt = Math.min(Math.max((now - lastFrameTime) / 1000, 0.001), 0.1)
|
|
@@ -2797,6 +2801,9 @@ function buildFrameSectionNodes() {
|
|
|
2797
2801
|
{
|
|
2798
2802
|
id: 'scene-graph-tick',
|
|
2799
2803
|
reads: ['frameDt', 'isEditorFrame', 'localId'], writes: ['sceneGraphMoved'],
|
|
2804
|
+
// Intentionally-terminal completion marker: no downstream node reads sceneGraphMoved, it just
|
|
2805
|
+
// records that this frame's scene-graph tick happened (inspectable via window.__renderGraph).
|
|
2806
|
+
terminal: true,
|
|
2800
2807
|
run(ctx) {
|
|
2801
2808
|
const lid = ctx.res.localId
|
|
2802
2809
|
if (_hierarchyDirty && latestState && latestState.entities.length > 0) { el.rebuildEntityHierarchy(latestState.entities); _hierarchyDirty = false }
|
|
@@ -2830,6 +2837,9 @@ function buildFrameSectionNodes() {
|
|
|
2830
2837
|
{
|
|
2831
2838
|
id: 'app-dispatch-frame',
|
|
2832
2839
|
reads: ['frameDt'], writes: ['appFrameDispatched'],
|
|
2840
|
+
// Intentionally-terminal completion marker: no downstream node reads appFrameDispatched, it
|
|
2841
|
+
// just records that this frame's app dispatch happened (inspectable via window.__renderGraph).
|
|
2842
|
+
terminal: true,
|
|
2833
2843
|
run(ctx) {
|
|
2834
2844
|
ams.dispatchFrame(ctx.res.frameDt, engineCtx)
|
|
2835
2845
|
if (engineCtx.facial) engineCtx.facial.update(ctx.res.frameDt)
|
|
@@ -2853,6 +2863,10 @@ function buildFrameSectionNodes() {
|
|
|
2853
2863
|
{
|
|
2854
2864
|
id: 'camera-input-update',
|
|
2855
2865
|
reads: ['frameDt', 'isEditorFrame', 'localId'], writes: ['localState', 'vegFocus'],
|
|
2866
|
+
// localState is a debug mirror (inspectable via window.__renderGraph) with no downstream
|
|
2867
|
+
// graph reader by design; vegFocus IS read (floating-origin-rebase), so only localState is
|
|
2868
|
+
// exempt here, not the whole node.
|
|
2869
|
+
debugMirrors: ['localState'],
|
|
2856
2870
|
run(ctx) {
|
|
2857
2871
|
const lid = ctx.res.localId
|
|
2858
2872
|
const local = client.getLocalState() || pm.playerStates.get(lid)
|
|
@@ -2901,6 +2915,9 @@ function buildFrameSectionNodes() {
|
|
|
2901
2915
|
// *shape* changes from {position:[...]} to {x,y,z}, both read the same way by consumers below).
|
|
2902
2916
|
id: 'floating-origin-rebase',
|
|
2903
2917
|
reads: ['vegFocus'], writes: ['originRebased'],
|
|
2918
|
+
// Intentionally-terminal completion marker: no downstream node reads originRebased, it just
|
|
2919
|
+
// records whether this frame rebased (inspectable via window.__renderGraph).
|
|
2920
|
+
terminal: true,
|
|
2904
2921
|
run(ctx) {
|
|
2905
2922
|
const p = camera.position
|
|
2906
2923
|
const rebased = floatingOrigin.update(p.x, p.y, p.z)
|
|
@@ -2962,6 +2979,9 @@ function buildFrameSectionNodes() {
|
|
|
2962
2979
|
{
|
|
2963
2980
|
id: 'shadow-move-gate',
|
|
2964
2981
|
reads: ['localId'], writes: ['shadowMoved'],
|
|
2982
|
+
// Intentionally-terminal completion marker: no downstream node reads shadowMoved, it just
|
|
2983
|
+
// records whether this frame's shadow camera moved (inspectable via window.__renderGraph).
|
|
2984
|
+
terminal: true,
|
|
2965
2985
|
run(ctx) {
|
|
2966
2986
|
const _shadowTgt = pm.playerMeshes.get(ctx.res.localId)?.position || camera.position
|
|
2967
2987
|
// ShadowPipeline (single owner) follows the player with a TEXEL-SNAPPED shadow camera so the
|
|
@@ -77,16 +77,6 @@ export function createRenderGraph(nodes, opts = {}) {
|
|
|
77
77
|
if (!readersOf.has(key)) readersOf.set(key, [])
|
|
78
78
|
readersOf.get(key).push(n.id)
|
|
79
79
|
}
|
|
80
|
-
// written-never-read: a construction-time warning, not an error (a terminal debug mirror is legal,
|
|
81
|
-
// but an unread resource is usually a consumer someone forgot to wire -- the silently-dropped-
|
|
82
|
-
// bridge class this repo keeps re-finding).
|
|
83
|
-
const unreadKeys = []
|
|
84
|
-
for (const [key, writer] of writerOf) {
|
|
85
|
-
if (!readersOf.has(key)) {
|
|
86
|
-
unreadKeys.push(key)
|
|
87
|
-
console.warn(`[render-graph] resource '${key}' (written by '${writer}') has no reader -- debug mirror or missing consumer?`)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
80
|
// Render-target aliasing (the other tractable half of the row): group resource KEYS by their
|
|
91
81
|
// declared physical target (node.targets[key], defaulting to the key itself -- i.e. "no sharing
|
|
92
82
|
// assumed" unless a node author opts in). Two distinct keys sharing one target is legitimate
|
|
@@ -112,6 +102,25 @@ export function createRenderGraph(nodes, opts = {}) {
|
|
|
112
102
|
if (!keysByTarget.has(target)) keysByTarget.set(target, [])
|
|
113
103
|
keysByTarget.get(target).push({ key, writer: writerOf.get(key) })
|
|
114
104
|
}
|
|
105
|
+
// written-never-read: a construction-time warning, not an error (a terminal debug mirror is legal,
|
|
106
|
+
// but an unread resource is usually a consumer someone forgot to wire -- the silently-dropped-
|
|
107
|
+
// bridge class this repo keeps re-finding). Exempt: (1) a declared non-self target -- the
|
|
108
|
+
// canvas/physical-target IS the real consumer, same as dead-pass detection below; (2) a writer
|
|
109
|
+
// node marked required/terminal -- the WHOLE node is an intentionally-terminal completion marker;
|
|
110
|
+
// (3) a key listed in the writer's own `debugMirrors` -- a PER-KEY escape for a node that writes
|
|
111
|
+
// some resources real consumers read and others that are deliberately self-contained debug
|
|
112
|
+
// mirrors (e.g. terrain-depth-color's 'camera-context', read inline via ctx.res, not a declared
|
|
113
|
+
// `reads` edge), so marking the whole node terminal would wrongly also silence a genuinely-
|
|
114
|
+
// missing consumer on one of its OTHER writes.
|
|
115
|
+
const unreadKeys = []
|
|
116
|
+
for (const [key, writer] of writerOf) {
|
|
117
|
+
if (readersOf.has(key) || hasDeclaredTarget.has(key)) continue
|
|
118
|
+
const writerNode = byId.get(writer)
|
|
119
|
+
if (writerNode && (writerNode.required || writerNode.terminal)) continue
|
|
120
|
+
if (writerNode && writerNode.debugMirrors && writerNode.debugMirrors.includes(key)) continue
|
|
121
|
+
unreadKeys.push(key)
|
|
122
|
+
console.warn(`[render-graph] resource '${key}' (written by '${writer}') has no reader -- debug mirror or missing consumer?`)
|
|
123
|
+
}
|
|
115
124
|
// Dead-pass detection (construction-time, static -- the tractable half of "auto-cull dead
|
|
116
125
|
// passes"): a node whose EVERY declared write is BOTH unread by another node's `reads` AND not
|
|
117
126
|
// aliased onto a shared physical target (targets[key]) is a real candidate for a forgotten/
|
|
@@ -83,6 +83,10 @@ export function buildRenderSectionNodes() {
|
|
|
83
83
|
reads: ['hostNearFar'],
|
|
84
84
|
writes: ['camera-context', 'terrainDepth', 'terrainColor'],
|
|
85
85
|
targets: { terrainDepth: 'canvas', terrainColor: 'canvas' },
|
|
86
|
+
// 'camera-context' is read inline via ctx.res['camera-context'] below (a same-node self-
|
|
87
|
+
// consume), never through a declared `reads` edge -- a real, intentional debug mirror, not a
|
|
88
|
+
// forgotten consumer.
|
|
89
|
+
debugMirrors: ['camera-context'],
|
|
86
90
|
shouldRun: ctx => !!ctx.terrainBackdrop,
|
|
87
91
|
run(ctx) {
|
|
88
92
|
ctx.terrainBackdrop.renderPlanet(ctx.camera, ctx.now / 1000, ctx.sun, ctx.floatingOrigin ? ctx.floatingOrigin.toAuthoritative : undefined)
|
|
@@ -256,6 +260,9 @@ export function buildRenderSectionNodes() {
|
|
|
256
260
|
id: 'visibility-commit',
|
|
257
261
|
reads: ['sceneDepth'],
|
|
258
262
|
writes: ['occlusionCommitted'],
|
|
263
|
+
// Intentionally-terminal completion marker (see comment below): no downstream node reads
|
|
264
|
+
// occlusionCommitted, it just stamps that this frame's queries were issued.
|
|
265
|
+
terminal: true,
|
|
259
266
|
// occlusionCommitted is a pure "queries issued this frame" stamp -- no other node reads it;
|
|
260
267
|
// this node's real effect is entirely external (GPU occlusion-query submission whose results
|
|
261
268
|
// land next frame via modelPool/terrainBackdrop/sceneOcclusion's own internal state, not a
|
package/package.json
CHANGED
package/src/apps/AppLoader.js
CHANGED
|
@@ -250,7 +250,7 @@ export class AppLoader {
|
|
|
250
250
|
revokes.push(url)
|
|
251
251
|
urlMap[spec] = url
|
|
252
252
|
}
|
|
253
|
-
return source.replace(/((?:from|import)\s*)(['"])(\.[^'"]+)\2/g, (m, pre, q, spec) =>
|
|
253
|
+
return source.replace(/((?:from|import)\s*)(['"])(\.[^'"]+|\/[^'"]+)\2/g, (m, pre, q, spec) =>
|
|
254
254
|
urlMap[spec] ? `${pre}${q}${urlMap[spec]}${q}` : m
|
|
255
255
|
)
|
|
256
256
|
}
|