@nexart/ui-renderer 0.8.6 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @nexart/ui-renderer
|
|
2
2
|
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.7
|
|
4
4
|
|
|
5
5
|
**Lightweight Preview Runtime for NexArt Protocol**
|
|
6
6
|
|
|
@@ -19,31 +19,35 @@ Version: 0.8.6
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
-
## v0.8.
|
|
22
|
+
## v0.8.7 — Live Runtime Binding Fix
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Fixed critical bug where time-varying properties were frozen in loop mode.
|
|
25
25
|
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **No flashing**: Canvas only updates when draw() runs
|
|
26
|
+
- **Live binding**: `frameCount`, `t`, `time`, `tGlobal`, `totalFrames` now update every frame
|
|
27
|
+
- **Proxy + with pattern**: Uses a Proxy scope with `with()` for live property access
|
|
28
|
+
- **Animations work**: Sketches see correct values on every frame
|
|
30
29
|
|
|
31
|
-
**Animation
|
|
30
|
+
**Animation Semantics:**
|
|
31
|
+
In loop mode, all time variables update every frame:
|
|
32
|
+
- `frameCount`: Increments each frame
|
|
33
|
+
- `t`: Normalized time `(frameCount % totalFrames) / totalFrames` (range [0,1))
|
|
34
|
+
- `time`: Alias for `t`
|
|
35
|
+
- `tGlobal`: Alias for `t`
|
|
36
|
+
- `totalFrames`: Total frames in the loop (default 120)
|
|
37
|
+
|
|
38
|
+
**Test Sketch:**
|
|
32
39
|
```javascript
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
function draw() {
|
|
41
|
+
background(0);
|
|
42
|
+
fill(255);
|
|
43
|
+
circle(
|
|
44
|
+
width / 2 + sin(frameCount * 0.1) * 300,
|
|
45
|
+
height / 2,
|
|
46
|
+
120
|
|
47
|
+
);
|
|
40
48
|
}
|
|
41
49
|
```
|
|
42
|
-
|
|
43
|
-
**Behavior:**
|
|
44
|
-
- Renders continuously at 8 FPS
|
|
45
|
-
- Modulo-based looping: `t = (frameCount % totalFrames) / totalFrames`
|
|
46
|
-
- Stops only when `stop()` is called
|
|
50
|
+
Expected: Circle moves horizontally, motion is continuous.
|
|
47
51
|
|
|
48
52
|
---
|
|
49
53
|
|
|
@@ -269,7 +273,7 @@ import { getCapabilities } from '@nexart/ui-renderer';
|
|
|
269
273
|
|
|
270
274
|
const caps = getCapabilities();
|
|
271
275
|
// {
|
|
272
|
-
// version: '0.8.
|
|
276
|
+
// version: '0.8.7',
|
|
273
277
|
// isCanonical: false,
|
|
274
278
|
// isArchival: false,
|
|
275
279
|
// previewBudget: { MAX_FRAMES: 30, MAX_TOTAL_TIME_MS: 500, FRAME_STRIDE: 3 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/code-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAwBjE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AAwBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,YAAY,
|
|
1
|
+
{"version":3,"file":"code-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/code-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAwBjE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AAwBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,YAAY,CAoTd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @nexart/ui-renderer v0.8.
|
|
2
|
+
* @nexart/ui-renderer v0.8.7 - Code Mode Renderer
|
|
3
3
|
*
|
|
4
4
|
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
5
5
|
* ║ PREVIEW RENDERER — LIGHTWEIGHT, NON-AUTHORITATIVE ║
|
|
@@ -85,19 +85,68 @@ export function renderCodeModeSystem(system, canvas, options = {}) {
|
|
|
85
85
|
const totalFrames = system.totalFrames ?? 120;
|
|
86
86
|
runtime.totalFrames = totalFrames;
|
|
87
87
|
try {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
// ╔═══════════════════════════════════════════════════════════════════════╗
|
|
89
|
+
// ║ LIVE RUNTIME BINDING — v0.8.7 FIX ║
|
|
90
|
+
// ║ ║
|
|
91
|
+
// ║ Time-varying properties (frameCount, t, time, tGlobal, totalFrames) ║
|
|
92
|
+
// ║ must be accessed via getters that read from the live runtime object. ║
|
|
93
|
+
// ║ ║
|
|
94
|
+
// ║ We use a Proxy + with() pattern to enable bare-name access to live ║
|
|
95
|
+
// ║ runtime properties. The proxy's get trap reads from runtime for ║
|
|
96
|
+
// ║ time-varying props, and from a static cache for everything else. ║
|
|
97
|
+
// ╚═══════════════════════════════════════════════════════════════════════╝
|
|
98
|
+
// Time-varying properties that need live access
|
|
99
|
+
const liveProps = new Set(['frameCount', 't', 'time', 'tGlobal', 'totalFrames']);
|
|
100
|
+
// Cache static properties (functions, constants)
|
|
101
|
+
const staticCache = {};
|
|
102
|
+
for (const key of Object.keys(runtime)) {
|
|
103
|
+
if (!liveProps.has(key)) {
|
|
104
|
+
staticCache[key] = runtime[key];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
const registerSetup = (fn) => { setupFn = fn; };
|
|
96
108
|
const registerDraw = (fn) => { drawFn = fn; };
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
// Build the set of all known keys (for has trap)
|
|
110
|
+
const knownKeys = new Set([
|
|
111
|
+
...liveProps,
|
|
112
|
+
...Object.keys(staticCache),
|
|
113
|
+
'__registerSetup',
|
|
114
|
+
'__registerDraw'
|
|
115
|
+
]);
|
|
116
|
+
// Create a proxy that provides live access to time-varying properties
|
|
117
|
+
// IMPORTANT: has() must return true ONLY for known keys
|
|
118
|
+
// Otherwise globals (Math, window, etc.) are masked and become undefined
|
|
119
|
+
const runtimeRef = runtime;
|
|
120
|
+
const scope = new Proxy({}, {
|
|
121
|
+
has: (_, prop) => knownKeys.has(prop),
|
|
122
|
+
get: (_, prop) => {
|
|
123
|
+
// Time-varying properties - read live from runtime
|
|
124
|
+
if (liveProps.has(prop)) {
|
|
125
|
+
return runtimeRef[prop];
|
|
126
|
+
}
|
|
127
|
+
// Special functions
|
|
128
|
+
if (prop === '__registerSetup')
|
|
129
|
+
return registerSetup;
|
|
130
|
+
if (prop === '__registerDraw')
|
|
131
|
+
return registerDraw;
|
|
132
|
+
// Static properties from cache
|
|
133
|
+
if (prop in staticCache)
|
|
134
|
+
return staticCache[prop];
|
|
135
|
+
// Fall through to undefined (should not hit this if has() is correct)
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// Use with() to make the proxy scope available to bare variable names
|
|
140
|
+
// Note: with() is safe here since we control the scope completely
|
|
141
|
+
const wrappedSource = `
|
|
142
|
+
with (__scope) {
|
|
143
|
+
${system.source}
|
|
144
|
+
if (typeof setup === 'function') __registerSetup(setup);
|
|
145
|
+
if (typeof draw === 'function') __registerDraw(draw);
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
const fn = new Function('__scope', wrappedSource);
|
|
149
|
+
fn(scope);
|
|
101
150
|
}
|
|
102
151
|
catch (error) {
|
|
103
152
|
console.warn('[UIRenderer] Compile error:', error);
|
package/package.json
CHANGED