mirage-engine 0.1.1

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.
@@ -0,0 +1,8 @@
1
+ export declare class Mirage {
2
+ private renderer;
3
+ private syncer;
4
+ private target;
5
+ constructor(selector: string);
6
+ start(): void;
7
+ stop(): void;
8
+ }
@@ -0,0 +1,18 @@
1
+ import { Renderer } from '../renderer/Renderer';
2
+ export declare class Syncer {
3
+ private target;
4
+ private renderer;
5
+ private observer;
6
+ private isDomDirty;
7
+ private isRunning;
8
+ private mutationTimer;
9
+ private cssTimer;
10
+ constructor(target: HTMLElement, renderer: Renderer);
11
+ start(): void;
12
+ stop(): void;
13
+ private clearTimers;
14
+ private onTransitionFinished;
15
+ private onWindowResize;
16
+ private forceUpdateScene;
17
+ private renderLoop;
18
+ }
@@ -0,0 +1,2 @@
1
+ import { SceneNode } from '../types';
2
+ export declare function extractSceneGraph(element: HTMLElement): SceneNode | null;
@@ -0,0 +1 @@
1
+ export { Mirage } from './core/Mirage';
@@ -0,0 +1,176 @@
1
+ var p = Object.defineProperty;
2
+ var v = (r, e, t) => e in r ? p(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
+ var i = (r, e, t) => (v(r, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import * as h from "three";
5
+ class S {
6
+ constructor() {
7
+ i(this, "canvas");
8
+ i(this, "scene");
9
+ i(this, "camera");
10
+ i(this, "renderer");
11
+ i(this, "renderOrder", 0);
12
+ this.canvas = document.createElement("canvas"), this.scene = new h.Scene();
13
+ const e = window.innerWidth, t = window.innerHeight;
14
+ this.camera = new h.OrthographicCamera(
15
+ e / -2,
16
+ e / 2,
17
+ t / 2,
18
+ t / -2,
19
+ 1,
20
+ 1e3
21
+ ), this.camera.position.z = 100, this.renderer = new h.WebGLRenderer({
22
+ canvas: this.canvas,
23
+ alpha: !0
24
+ }), this.renderer.setSize(e, t);
25
+ }
26
+ mount(e) {
27
+ e.appendChild(this.canvas);
28
+ }
29
+ dispose() {
30
+ try {
31
+ this.renderer.dispose();
32
+ } catch {
33
+ }
34
+ this.canvas.parentElement && this.canvas.parentElement.removeChild(this.canvas);
35
+ }
36
+ setSize(e, t) {
37
+ this.renderer.setSize(e, t), this.camera.left = e / -2, this.camera.right = e / 2, this.camera.top = t / 2, this.camera.bottom = t / -2, this.camera.updateProjectionMatrix();
38
+ }
39
+ clearScene() {
40
+ for (; this.scene.children.length > 0; )
41
+ this.scene.remove(this.scene.children[0]);
42
+ }
43
+ buildScene(e) {
44
+ if (e.type === "BOX") {
45
+ const t = new h.PlaneGeometry(
46
+ e.rect.width,
47
+ e.rect.height
48
+ ), s = e.styles.backgroundColor;
49
+ let o = s, n = 1;
50
+ if (s === "transparent" || s === "rgba(0, 0, 0, 0)")
51
+ o = "#ffffff", n = 0;
52
+ else if (s.startsWith("rgba")) {
53
+ const a = s.match(/[\d.]+/g);
54
+ if (a && a.length >= 4) {
55
+ const g = a[0], y = a[1], T = a[2];
56
+ n = parseFloat(a[3]), o = `rgb(${g}, ${y}, ${T})`;
57
+ }
58
+ }
59
+ const c = e.styles.opacity * n, d = new h.MeshBasicMaterial({
60
+ color: o,
61
+ opacity: c,
62
+ transparent: c < 1
63
+ }), l = new h.Mesh(t, d), u = this.renderer.domElement.width, f = this.renderer.domElement.height, w = 1e-3;
64
+ this.renderOrder++, l.position.set(
65
+ e.rect.x - u / 2 + e.rect.width / 2,
66
+ -e.rect.y + f / 2 - e.rect.height / 2,
67
+ e.styles.zIndex + this.renderOrder * w
68
+ ), this.scene.add(l);
69
+ for (const a of e.children)
70
+ this.buildScene(a);
71
+ }
72
+ }
73
+ syncScene(e) {
74
+ this.clearScene(), this.renderOrder = 0, this.buildScene(e);
75
+ }
76
+ render() {
77
+ this.renderer.render(this.scene, this.camera);
78
+ }
79
+ }
80
+ function m(r) {
81
+ if (r.tagName === "SCRIPT" || r.tagName === "STYLE")
82
+ return null;
83
+ const e = r.getBoundingClientRect(), t = {
84
+ x: e.x + window.scrollX,
85
+ y: e.y + window.scrollY,
86
+ width: e.width,
87
+ height: e.height
88
+ }, s = window.getComputedStyle(r), o = {
89
+ backgroundColor: s.backgroundColor,
90
+ opacity: parseFloat(s.opacity),
91
+ zIndex: parseInt(s.zIndex, 10) || 0
92
+ }, n = [];
93
+ for (const c of r.children) {
94
+ const d = m(c);
95
+ d && n.push(d);
96
+ }
97
+ return {
98
+ type: "BOX",
99
+ rect: t,
100
+ styles: o,
101
+ children: n
102
+ };
103
+ }
104
+ class b {
105
+ constructor(e, t) {
106
+ i(this, "target");
107
+ i(this, "renderer");
108
+ i(this, "observer");
109
+ i(this, "isDomDirty", !1);
110
+ i(this, "isRunning", !1);
111
+ i(this, "mutationTimer", null);
112
+ i(this, "cssTimer", null);
113
+ i(this, "onTransitionFinished", (e) => {
114
+ this.target.contains(e.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.cssTimer = window.setTimeout(() => {
115
+ this.isDomDirty = !0, this.cssTimer = null;
116
+ }, 50));
117
+ });
118
+ i(this, "onWindowResize", () => {
119
+ this.renderer.setSize(window.innerWidth, window.innerHeight), this.isDomDirty = !0;
120
+ });
121
+ i(this, "renderLoop", () => {
122
+ this.isRunning && (this.isDomDirty && this.forceUpdateScene(), this.renderer.render(), requestAnimationFrame(this.renderLoop));
123
+ });
124
+ this.target = e, this.renderer = t, this.observer = new MutationObserver((s) => {
125
+ let o = !1, n = !1;
126
+ for (const c of s)
127
+ c.type === "childList" ? o = !0 : c.type === "attributes" && (n = !0);
128
+ if (o) {
129
+ this.clearTimers(), console.log("Structural Changed"), this.isDomDirty = !0;
130
+ return;
131
+ }
132
+ n && (this.mutationTimer && clearTimeout(this.mutationTimer), this.mutationTimer = window.setTimeout(() => {
133
+ this.mutationTimer = null, this.isDomDirty = !0;
134
+ }, 200));
135
+ });
136
+ }
137
+ start() {
138
+ this.isRunning || (this.isRunning = !0, this.observer.observe(this.target, {
139
+ childList: !0,
140
+ subtree: !0,
141
+ attributes: !0,
142
+ characterData: !0
143
+ }), this.target.addEventListener("transitionend", this.onTransitionFinished), this.target.addEventListener("animationend", this.onTransitionFinished), window.addEventListener("resize", this.onWindowResize), this.forceUpdateScene(), this.renderLoop());
144
+ }
145
+ stop() {
146
+ this.isRunning = !1, this.observer.disconnect(), this.clearTimers(), this.target.removeEventListener("transitionend", this.onTransitionFinished), this.target.removeEventListener("animationend", this.onTransitionFinished), window.removeEventListener("resize", this.onWindowResize);
147
+ }
148
+ clearTimers() {
149
+ this.mutationTimer && (clearTimeout(this.mutationTimer), this.mutationTimer = null), this.cssTimer && (clearTimeout(this.cssTimer), this.cssTimer = null);
150
+ }
151
+ forceUpdateScene() {
152
+ this.isDomDirty = !1;
153
+ const e = m(this.target);
154
+ e && this.renderer.syncScene(e);
155
+ }
156
+ }
157
+ class C {
158
+ constructor(e) {
159
+ i(this, "renderer");
160
+ i(this, "syncer");
161
+ i(this, "target");
162
+ const t = document.querySelector(e);
163
+ if (!t)
164
+ throw new Error(`[Mirage] Element not found: ${e}`);
165
+ this.target = t, this.renderer = new S(), this.renderer.mount(document.body), this.syncer = new b(this.target, this.renderer);
166
+ }
167
+ start() {
168
+ this.syncer.start();
169
+ }
170
+ stop() {
171
+ this.syncer.stop(), this.renderer.dispose();
172
+ }
173
+ }
174
+ export {
175
+ C as Mirage
176
+ };
@@ -0,0 +1 @@
1
+ (function(s,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],o):(s=typeof globalThis<"u"?globalThis:s||self,o(s.MirageEngine={},s.THREE))})(this,function(s,o){"use strict";var O=Object.defineProperty;var C=(s,o,d)=>o in s?O(s,o,{enumerable:!0,configurable:!0,writable:!0,value:d}):s[o]=d;var i=(s,o,d)=>(C(s,typeof o!="symbol"?o+"":o,d),d);function d(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const u=d(o);class y{constructor(){i(this,"canvas");i(this,"scene");i(this,"camera");i(this,"renderer");i(this,"renderOrder",0);this.canvas=document.createElement("canvas"),this.scene=new u.Scene;const e=window.innerWidth,t=window.innerHeight;this.camera=new u.OrthographicCamera(e/-2,e/2,t/2,t/-2,1,1e3),this.camera.position.z=100,this.renderer=new u.WebGLRenderer({canvas:this.canvas,alpha:!0}),this.renderer.setSize(e,t)}mount(e){e.appendChild(this.canvas)}dispose(){try{this.renderer.dispose()}catch{}this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}setSize(e,t){this.renderer.setSize(e,t),this.camera.left=e/-2,this.camera.right=e/2,this.camera.top=t/2,this.camera.bottom=t/-2,this.camera.updateProjectionMatrix()}clearScene(){for(;this.scene.children.length>0;)this.scene.remove(this.scene.children[0])}buildScene(e){if(e.type==="BOX"){const t=new u.PlaneGeometry(e.rect.width,e.rect.height),n=e.styles.backgroundColor;let c=n,a=1;if(n==="transparent"||n==="rgba(0, 0, 0, 0)")c="#ffffff",a=0;else if(n.startsWith("rgba")){const h=n.match(/[\d.]+/g);if(h&&h.length>=4){const S=h[0],E=h[1],D=h[2];a=parseFloat(h[3]),c=`rgb(${S}, ${E}, ${D})`}}const l=e.styles.opacity*a,m=new u.MeshBasicMaterial({color:c,opacity:l,transparent:l<1}),g=new u.Mesh(t,m),T=this.renderer.domElement.width,b=this.renderer.domElement.height,v=.001;this.renderOrder++,g.position.set(e.rect.x-T/2+e.rect.width/2,-e.rect.y+b/2-e.rect.height/2,e.styles.zIndex+this.renderOrder*v),this.scene.add(g);for(const h of e.children)this.buildScene(h)}}syncScene(e){this.clearScene(),this.renderOrder=0,this.buildScene(e)}render(){this.renderer.render(this.scene,this.camera)}}function f(r){if(r.tagName==="SCRIPT"||r.tagName==="STYLE")return null;const e=r.getBoundingClientRect(),t={x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height},n=window.getComputedStyle(r),c={backgroundColor:n.backgroundColor,opacity:parseFloat(n.opacity),zIndex:parseInt(n.zIndex,10)||0},a=[];for(const l of r.children){const m=f(l);m&&a.push(m)}return{type:"BOX",rect:t,styles:c,children:a}}class p{constructor(e,t){i(this,"target");i(this,"renderer");i(this,"observer");i(this,"isDomDirty",!1);i(this,"isRunning",!1);i(this,"mutationTimer",null);i(this,"cssTimer",null);i(this,"onTransitionFinished",e=>{this.target.contains(e.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50))});i(this,"onWindowResize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight),this.isDomDirty=!0});i(this,"renderLoop",()=>{this.isRunning&&(this.isDomDirty&&this.forceUpdateScene(),this.renderer.render(),requestAnimationFrame(this.renderLoop))});this.target=e,this.renderer=t,this.observer=new MutationObserver(n=>{let c=!1,a=!1;for(const l of n)l.type==="childList"?c=!0:l.type==="attributes"&&(a=!0);if(c){this.clearTimers(),console.log("Structural Changed"),this.isDomDirty=!0;return}a&&(this.mutationTimer&&clearTimeout(this.mutationTimer),this.mutationTimer=window.setTimeout(()=>{this.mutationTimer=null,this.isDomDirty=!0},200))})}start(){this.isRunning||(this.isRunning=!0,this.observer.observe(this.target,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),this.target.addEventListener("transitionend",this.onTransitionFinished),this.target.addEventListener("animationend",this.onTransitionFinished),window.addEventListener("resize",this.onWindowResize),this.forceUpdateScene(),this.renderLoop())}stop(){this.isRunning=!1,this.observer.disconnect(),this.clearTimers(),this.target.removeEventListener("transitionend",this.onTransitionFinished),this.target.removeEventListener("animationend",this.onTransitionFinished),window.removeEventListener("resize",this.onWindowResize)}clearTimers(){this.mutationTimer&&(clearTimeout(this.mutationTimer),this.mutationTimer=null),this.cssTimer&&(clearTimeout(this.cssTimer),this.cssTimer=null)}forceUpdateScene(){this.isDomDirty=!1;const e=f(this.target);e&&this.renderer.syncScene(e)}}class w{constructor(e){i(this,"renderer");i(this,"syncer");i(this,"target");const t=document.querySelector(e);if(!t)throw new Error(`[Mirage] Element not found: ${e}`);this.target=t,this.renderer=new y,this.renderer.mount(document.body),this.syncer=new p(this.target,this.renderer)}start(){this.syncer.start()}stop(){this.syncer.stop(),this.renderer.dispose()}}s.Mirage=w,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,4 @@
1
+ export declare function domToWebGL(x: number, y: number, canvasWidth: number, canvasHeight: number): {
2
+ x: number;
3
+ y: number;
4
+ };
@@ -0,0 +1,16 @@
1
+ import { SceneNode } from '../types';
2
+ export declare class Renderer {
3
+ readonly canvas: HTMLCanvasElement;
4
+ private readonly scene;
5
+ private readonly camera;
6
+ private readonly renderer;
7
+ private renderOrder;
8
+ constructor();
9
+ mount(parent: HTMLElement): void;
10
+ dispose(): void;
11
+ setSize(width: number, height: number): void;
12
+ private clearScene;
13
+ private buildScene;
14
+ syncScene(graphNode: SceneNode): void;
15
+ render(): void;
16
+ }
@@ -0,0 +1,17 @@
1
+ export interface NodeRect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface BoxStyles {
8
+ backgroundColor: string;
9
+ opacity: number;
10
+ zIndex: number;
11
+ }
12
+ export interface SceneNode {
13
+ type: "BOX";
14
+ rect: NodeRect;
15
+ styles: BoxStyles;
16
+ children: SceneNode[];
17
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "mirage-engine",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "types": "./dist/index.d.ts",
6
+ "main": "./dist/mirage-engine.umd.js",
7
+ "module": "./dist/mirage-engine.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/mirage-engine.js",
12
+ "require": "./dist/mirage-engine.umd.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "dev": "vite",
20
+ "build": "tsc && vite build",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "peerDependencies": {
24
+ "three": "^0.150.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/three": "^0.181.0",
28
+ "three": "^0.150.0",
29
+ "typescript": "^5.0.0",
30
+ "vite": "^4.0.0",
31
+ "vite-plugin-dts": "^4.5.4"
32
+ },
33
+ "keywords": ["webgl", "dom", "mirroring", "threejs", "typescript"],
34
+ "author": "dltldn333@gmail.com",
35
+ "license": "MIT"
36
+ }