@mirage-engine/core 0.2.2 → 0.3.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/CHANGELOG.md +12 -0
- package/dist/mirage-engine.js +990 -639
- package/dist/mirage-engine.umd.js +16 -10
- package/dist/src/animation/Animator.d.ts +1 -6
- package/dist/src/core/Engine.d.ts +3 -0
- package/dist/src/core/Syncer.d.ts +2 -20
- package/dist/src/dom/Extractor.d.ts +1 -2
- package/dist/src/renderer/Renderer.d.ts +7 -5
- package/dist/src/types/attributes.d.ts +63 -0
- package/dist/src/types/common.d.ts +4 -0
- package/dist/src/types/config.d.ts +2 -8
- package/dist/src/types/flags.d.ts +8 -7
- package/dist/src/types/index.d.ts +2 -1
- package/package.json +3 -2
- package/src/animation/Animator.ts +2 -57
- package/src/core/Engine.ts +14 -2
- package/src/core/Syncer.ts +39 -235
- package/src/dom/Extractor.ts +357 -68
- package/src/renderer/Renderer.ts +283 -98
- package/src/store/TextureLifecycleManager.ts +24 -9
- package/src/types/attributes.ts +57 -0
- package/src/types/common.ts +4 -0
- package/src/types/config.ts +5 -10
- package/src/types/flags.ts +20 -15
- package/src/types/index.ts +2 -1
package/src/core/Engine.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CoreConfig } from "../types";
|
|
1
|
+
import { CoreConfig, ATTR_DOM } from "../types";
|
|
2
2
|
import { Renderer } from "../renderer/Renderer";
|
|
3
3
|
import { Syncer } from "./Syncer";
|
|
4
4
|
import { MeshRegistry } from "../store/MeshRegistry";
|
|
@@ -17,7 +17,7 @@ export class Engine {
|
|
|
17
17
|
const style = document.createElement("style");
|
|
18
18
|
style.id = "mirage-engine-styles";
|
|
19
19
|
style.textContent = `
|
|
20
|
-
[
|
|
20
|
+
[${ATTR_DOM.NAME}="${ATTR_DOM.VALUES.HIDE}"] {
|
|
21
21
|
opacity: 0 !important;
|
|
22
22
|
}
|
|
23
23
|
`;
|
|
@@ -59,6 +59,18 @@ export class Engine {
|
|
|
59
59
|
this.renderer.dispose();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
public getTracker() {
|
|
63
|
+
return this.syncer.tracker;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public updateUniforms(element: HTMLElement, uniforms: Record<string, any>) {
|
|
67
|
+
this.renderer.updateUniforms(element, uniforms);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public getCanvas() {
|
|
71
|
+
return this.renderer.canvas;
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
public test() {
|
|
63
75
|
const boxMesh = this.registry.get(
|
|
64
76
|
document.querySelector("#box2") as HTMLElement,
|
package/src/core/Syncer.ts
CHANGED
|
@@ -2,53 +2,17 @@ import { CoreConfig } from "../types/config";
|
|
|
2
2
|
import { Renderer } from "../renderer/Renderer";
|
|
3
3
|
import { MeshRegistry } from "../store/MeshRegistry";
|
|
4
4
|
import { extractSceneGraph } from "../dom/Extractor";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
DIRTY_STRUCTURE,
|
|
9
|
-
DIRTY_CONTENT
|
|
10
|
-
,
|
|
11
|
-
DIRTY_STYLE,
|
|
12
|
-
USER_LAYER,
|
|
13
|
-
SYSTEM_LAYER,
|
|
14
|
-
Visibility,
|
|
15
|
-
StyleData,
|
|
16
|
-
} from "../types";
|
|
17
|
-
import { extractFromStyle, animateMeshByData, updateFixedMeshesScroll } from "../animation/Animator";
|
|
18
|
-
|
|
19
|
-
interface InternalResizeConfig {
|
|
20
|
-
enabled: boolean;
|
|
21
|
-
delay: number;
|
|
22
|
-
onStart?: () => void;
|
|
23
|
-
onEnd?: () => void;
|
|
24
|
-
}
|
|
5
|
+
import { Visibility, USER_LAYER, ATTR_TRAVEL } from "../types";
|
|
6
|
+
import { animateMeshByData, updateFixedMeshesScroll } from "../animation/Animator";
|
|
7
|
+
import { Tracker } from "@mirage-engine/dom-tracker";
|
|
25
8
|
|
|
26
9
|
export class Syncer {
|
|
27
10
|
private target: HTMLElement;
|
|
28
11
|
private renderer: Renderer;
|
|
29
12
|
private registry: MeshRegistry;
|
|
30
|
-
private filter: CoreConfig["filter"];
|
|
31
|
-
|
|
32
|
-
private observer: MutationObserver;
|
|
33
|
-
private pendingDeletions: Set<HTMLElement> = new Set();
|
|
34
|
-
private pendingStyles: Map<HTMLElement, StyleData> = new Map();
|
|
35
|
-
|
|
36
|
-
private isDomDirty: boolean = false;
|
|
37
|
-
private isRunning: boolean = false;
|
|
38
13
|
private isTravelEnabled: boolean = false;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
private mutationTimer: number | null = null;
|
|
43
|
-
private cssTimer: number | null = null;
|
|
44
|
-
|
|
45
|
-
private resizeConfig: InternalResizeConfig;
|
|
46
|
-
private resizeTimer: number | null = null;
|
|
47
|
-
private isResizing: boolean = false;
|
|
48
|
-
|
|
49
|
-
private lastScrollX: number = 0;
|
|
50
|
-
private lastScrollY: number = 0;
|
|
51
|
-
private scrollTimer: number | null = null;
|
|
14
|
+
|
|
15
|
+
public tracker: Tracker;
|
|
52
16
|
|
|
53
17
|
constructor(
|
|
54
18
|
target: HTMLElement,
|
|
@@ -59,213 +23,53 @@ export class Syncer {
|
|
|
59
23
|
this.target = target;
|
|
60
24
|
this.renderer = renderer;
|
|
61
25
|
this.registry = registry;
|
|
62
|
-
this.filter = config.filter;
|
|
63
|
-
|
|
64
|
-
// Resize Debounce Configuration
|
|
65
|
-
const debounceOpt = config.resizeDebounce ?? true;
|
|
66
|
-
if (debounceOpt === false) {
|
|
67
|
-
this.resizeConfig = { enabled: false, delay: 0 };
|
|
68
|
-
} else if (debounceOpt === true) {
|
|
69
|
-
this.resizeConfig = { enabled: true, delay: 150 };
|
|
70
|
-
} else {
|
|
71
|
-
this.resizeConfig = {
|
|
72
|
-
enabled: true,
|
|
73
|
-
delay: debounceOpt.delay ?? 150,
|
|
74
|
-
onStart: debounceOpt.onStart,
|
|
75
|
-
onEnd: debounceOpt.onEnd,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.observer = new MutationObserver((mutations) => {
|
|
80
|
-
let currentMask = DIRTY_NONE;
|
|
81
26
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
mutation.removedNodes.forEach((node) => {
|
|
87
|
-
if (node instanceof HTMLElement) {
|
|
88
|
-
this.pendingDeletions.add(node);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
} else if (mutation.type === "attributes") {
|
|
93
|
-
if (mutation.attributeName === "style") {
|
|
94
|
-
currentMask |= DIRTY_RECT | DIRTY_STYLE;
|
|
95
|
-
const target = mutation.target as HTMLElement;
|
|
27
|
+
// Use Tracker from dom-tracker
|
|
28
|
+
this.tracker = new Tracker(target, {
|
|
29
|
+
resizeDebounce: config.resizeDebounce,
|
|
30
|
+
});
|
|
96
31
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// }
|
|
105
|
-
} else if (mutation.type === "characterData") {
|
|
106
|
-
currentMask |= DIRTY_CONTENT | DIRTY_RECT;
|
|
107
|
-
}
|
|
32
|
+
// Wire up the hooks
|
|
33
|
+
this.tracker.onLayoutChange.add((pendingMask, pendingDeletions) => {
|
|
34
|
+
const discoveredTraveler =
|
|
35
|
+
document.querySelector(`[${ATTR_TRAVEL.NAME}~='${ATTR_TRAVEL.VALUES.TRAVELER}']`) !== null;
|
|
36
|
+
if (discoveredTraveler && !this.isTravelEnabled) {
|
|
37
|
+
this.isTravelEnabled = true;
|
|
38
|
+
this.renderer.createRenderTarget();
|
|
108
39
|
}
|
|
109
40
|
|
|
110
|
-
|
|
111
|
-
this.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
this.mutationTimer = window.setTimeout(() => {
|
|
123
|
-
this.mutationTimer = null;
|
|
124
|
-
this.isDomDirty = true;
|
|
125
|
-
}, 200);
|
|
41
|
+
const sceneGraph = extractSceneGraph(
|
|
42
|
+
this.target,
|
|
43
|
+
pendingMask,
|
|
44
|
+
USER_LAYER as Visibility,
|
|
45
|
+
1,
|
|
46
|
+
0,
|
|
47
|
+
this.renderer.qualityFactor
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (sceneGraph) {
|
|
51
|
+
this.renderer.syncScene(sceneGraph, pendingDeletions);
|
|
126
52
|
}
|
|
127
53
|
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public start() {
|
|
131
|
-
if (this.isRunning) return;
|
|
132
|
-
this.isRunning = true;
|
|
133
54
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
childList: true,
|
|
137
|
-
subtree: true,
|
|
138
|
-
attributes: true,
|
|
139
|
-
characterData: true,
|
|
55
|
+
this.tracker.onScrollChange.add((scrollX, scrollY) => {
|
|
56
|
+
updateFixedMeshesScroll(this.renderer.fixedMeshes, scrollX, scrollY);
|
|
140
57
|
});
|
|
141
58
|
|
|
142
|
-
this.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this.forceUpdateScene();
|
|
147
|
-
this.renderLoop();
|
|
148
|
-
// for debugging
|
|
149
|
-
// this.renderer.showScissoredRenderTarget();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
public stop() {
|
|
153
|
-
this.isRunning = false;
|
|
154
|
-
this.observer.disconnect();
|
|
155
|
-
|
|
156
|
-
this.clearTimers();
|
|
59
|
+
this.tracker.onStyleChange.add((pendingStyles) => {
|
|
60
|
+
animateMeshByData(this.registry, pendingStyles);
|
|
61
|
+
});
|
|
157
62
|
|
|
158
|
-
this.
|
|
159
|
-
|
|
160
|
-
|
|
63
|
+
this.tracker.onRender.add(() => {
|
|
64
|
+
this.renderer.render();
|
|
65
|
+
});
|
|
161
66
|
}
|
|
162
67
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
clearTimeout(this.mutationTimer);
|
|
166
|
-
this.mutationTimer = null;
|
|
167
|
-
}
|
|
168
|
-
if (this.cssTimer) {
|
|
169
|
-
clearTimeout(this.cssTimer);
|
|
170
|
-
this.cssTimer = null;
|
|
171
|
-
}
|
|
172
|
-
if (this.scrollTimer) {
|
|
173
|
-
clearTimeout(this.scrollTimer);
|
|
174
|
-
this.scrollTimer = null;
|
|
175
|
-
}
|
|
68
|
+
public start() {
|
|
69
|
+
this.tracker.start();
|
|
176
70
|
}
|
|
177
71
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (this.mutationTimer !== null) return;
|
|
181
|
-
if (this.cssTimer) clearTimeout(this.cssTimer);
|
|
182
|
-
if (this.pendingStyles.size != 0) return;
|
|
183
|
-
this.pendingMask |= DIRTY_RECT | DIRTY_STYLE;
|
|
184
|
-
this.cssTimer = window.setTimeout(() => {
|
|
185
|
-
this.isDomDirty = true;
|
|
186
|
-
this.cssTimer = null;
|
|
187
|
-
}, 50);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
private onWindowResize = () => {
|
|
191
|
-
if (!this.resizeConfig.enabled) {
|
|
192
|
-
this.isDomDirty = true;
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
if (!this.isResizing) {
|
|
196
|
-
this.isResizing = true;
|
|
197
|
-
if (this.resizeConfig.onStart) this.resizeConfig.onStart();
|
|
198
|
-
}
|
|
199
|
-
if (this.resizeTimer) clearTimeout(this.resizeTimer);
|
|
200
|
-
this.resizeTimer = window.setTimeout(() => {
|
|
201
|
-
this.isDomDirty = true;
|
|
202
|
-
if (this.resizeConfig.onEnd) this.resizeConfig.onEnd();
|
|
203
|
-
this.isResizing = false;
|
|
204
|
-
this.resizeTimer = null;
|
|
205
|
-
}, this.resizeConfig.delay);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
private forceUpdateScene() {
|
|
209
|
-
this.isDomDirty = false;
|
|
210
|
-
|
|
211
|
-
this.lastScrollX = window.scrollX;
|
|
212
|
-
this.lastScrollY = window.scrollY;
|
|
213
|
-
|
|
214
|
-
const discoveredTraveler =
|
|
215
|
-
document.querySelector("[data-mirage-travel='traveler']") !== null;
|
|
216
|
-
if (discoveredTraveler && !this.isTravelEnabled) {
|
|
217
|
-
this.isTravelEnabled = true;
|
|
218
|
-
this.renderer.createRenderTarget();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const sceneGraph = extractSceneGraph(
|
|
222
|
-
this.target,
|
|
223
|
-
this.pendingMask,
|
|
224
|
-
(discoveredTraveler
|
|
225
|
-
? USER_LAYER | SYSTEM_LAYER
|
|
226
|
-
: USER_LAYER) as Visibility,
|
|
227
|
-
this.filter,
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
if (sceneGraph) {
|
|
231
|
-
this.renderer.syncScene(sceneGraph, this.pendingDeletions);
|
|
232
|
-
this.pendingDeletions.clear();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
this.pendingMask = DIRTY_NONE;
|
|
72
|
+
public stop() {
|
|
73
|
+
this.tracker.stop();
|
|
236
74
|
}
|
|
237
|
-
|
|
238
|
-
private renderLoop = () => {
|
|
239
|
-
if (!this.isRunning) return;
|
|
240
|
-
|
|
241
|
-
if (this.isDomDirty) {
|
|
242
|
-
this.forceUpdateScene();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const currentScrollX = window.scrollX;
|
|
246
|
-
const currentScrollY = window.scrollY;
|
|
247
|
-
if (currentScrollX !== this.lastScrollX || currentScrollY !== this.lastScrollY) {
|
|
248
|
-
updateFixedMeshesScroll(this.renderer.fixedMeshes, currentScrollX, currentScrollY);
|
|
249
|
-
|
|
250
|
-
this.lastScrollX = currentScrollX;
|
|
251
|
-
this.lastScrollY = currentScrollY;
|
|
252
|
-
|
|
253
|
-
if (this.scrollTimer) clearTimeout(this.scrollTimer);
|
|
254
|
-
this.scrollTimer = window.setTimeout(() => {
|
|
255
|
-
this.pendingMask |= DIRTY_RECT;
|
|
256
|
-
this.isDomDirty = true;
|
|
257
|
-
this.scrollTimer = null;
|
|
258
|
-
}, 150);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (this.pendingStyles.size > 0) {
|
|
262
|
-
animateMeshByData(this.registry, this.pendingStyles);
|
|
263
|
-
this.pendingStyles.clear();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
this.renderer.render();
|
|
267
|
-
requestAnimationFrame(this.renderLoop);
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// [ThinkPoint] change call back pattern when after
|
|
271
75
|
}
|