@overglaze/web 0.0.0-stage → 0.9.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.
- package/LICENSE +98 -0
- package/README.md +63 -2
- package/desktops/desktop.js +40 -0
- package/desktops/fonts/DMMono-Medium.woff2 +0 -0
- package/desktops/fonts/DMMono-Regular.woff2 +0 -0
- package/desktops/fonts/NotoSerif-VF.woff2 +0 -0
- package/desktops/fonts/OFL-DMMono.txt +93 -0
- package/desktops/fonts/OFL-NotoSerif.txt +93 -0
- package/desktops/fonts/OFL-SpaceGrotesk.txt +93 -0
- package/desktops/fonts/SpaceGrotesk-Bold.woff2 +0 -0
- package/desktops/fonts/SpaceGrotesk-Medium.woff2 +0 -0
- package/desktops/fonts/SpaceGrotesk-Regular.woff2 +0 -0
- package/desktops/wallpapers.js +227 -0
- package/embed.css +53 -0
- package/embed.js +6 -0
- package/engine/core.js +6 -0
- package/engine/cursor.js +6 -0
- package/engine/descriptor.js +6 -0
- package/engine/files.js +6 -0
- package/engine/globals.js +6 -0
- package/engine/golden-globals.js +6 -0
- package/engine/imgui-ops.js +6 -0
- package/engine/keys.js +6 -0
- package/engine/modules.js +6 -0
- package/engine/naga.wasm +0 -0
- package/engine/naga.wasm.notices.txt +2344 -0
- package/engine/ops.js +6 -0
- package/engine/param-store.js +6 -0
- package/engine/plugin-js.wasm +0 -0
- package/engine/plugin-js.wasm.notices.txt +4411 -0
- package/engine/plugin-storage.js +6 -0
- package/engine/session.js +9 -0
- package/engine/shaders.js +7 -0
- package/engine/tex.js +6 -0
- package/engine/uniforms.js +6 -0
- package/engine/worker.js +74 -0
- package/host/api.js +30 -0
- package/host/assets.js +6 -0
- package/host/bootstrap.js +7 -0
- package/host/imgui.js +6 -0
- package/host/params.js +6 -0
- package/host/seeded_random.js +6 -0
- package/host/storage.js +6 -0
- package/host/webio.js +6 -0
- package/host/webshim.js +6 -0
- package/package.json +19 -4
- package/player/fill.js +6 -0
- package/player/panel.css +92 -0
- package/player/panel.js +6 -0
- package/player/player.css +210 -0
- package/player/player.js +6 -0
package/player/panel.css
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* The parameter panel's own look: a row per parameter, its label beside its
|
|
2
|
+
control, and each group under a heading rule. It takes the player's button
|
|
3
|
+
style for "Reset all" (player.css). A surface restyles it through the custom
|
|
4
|
+
properties below. */
|
|
5
|
+
|
|
6
|
+
.og-params {
|
|
7
|
+
--og-params-line: rgba(127, 127, 127, 0.35);
|
|
8
|
+
--og-params-quiet: 0.75;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 8px;
|
|
12
|
+
min-width: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.og-params-note {
|
|
16
|
+
margin: 0;
|
|
17
|
+
opacity: var(--og-params-quiet);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.og-param {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
|
|
23
|
+
gap: 2px 10px;
|
|
24
|
+
align-items: center;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.og-param-label {
|
|
28
|
+
overflow-wrap: anywhere;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.og-param-control {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 4px;
|
|
35
|
+
min-width: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.og-param-pair {
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 6px;
|
|
41
|
+
align-items: center;
|
|
42
|
+
min-width: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.og-param-pair input[type="range"] {
|
|
46
|
+
flex: 1 1 auto;
|
|
47
|
+
min-width: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.og-params input,
|
|
51
|
+
.og-params select {
|
|
52
|
+
font: inherit;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.og-param-number {
|
|
56
|
+
width: 6.5em;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.og-param-control > .og-param-number,
|
|
60
|
+
.og-param-control > select {
|
|
61
|
+
width: 100%;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* A hint stays on screen under its control, a line per value. */
|
|
65
|
+
.og-param-hint {
|
|
66
|
+
grid-column: 2;
|
|
67
|
+
margin: 0;
|
|
68
|
+
padding-left: 1.2em;
|
|
69
|
+
font-size: 0.9em;
|
|
70
|
+
opacity: var(--og-params-quiet);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.og-params-group {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 8px;
|
|
77
|
+
min-width: 0;
|
|
78
|
+
margin: 4px 0 0;
|
|
79
|
+
padding: 6px 0 0;
|
|
80
|
+
border: 0;
|
|
81
|
+
border-top: 1px solid var(--og-params-line);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.og-params-group > legend {
|
|
85
|
+
padding: 0 8px 0 0;
|
|
86
|
+
font-weight: 600;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.og-params-foot {
|
|
90
|
+
padding-top: 8px;
|
|
91
|
+
border-top: 1px solid var(--og-params-line);
|
|
92
|
+
}
|
package/player/panel.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*! Overglaze web engine. Licensed under the PolyForm Noncommercial License 1.0.0
|
|
2
|
+
* <https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
3
|
+
* Required Notice: Copyright (c) 2026 Svetlozar Kostadinov
|
|
4
|
+
* With an added permission to run it to develop and preview Overglaze plugins: see LICENSE in @overglaze/web
|
|
5
|
+
*/
|
|
6
|
+
var E=Object.defineProperty;var h=(d,e)=>E(d,"name",{value:e,configurable:!0});const y=["x","y","z","w"],k="Put every parameter back to the value this plugin declares, and forget what was saved.",N="This effect has no parameters to adjust.";let S=0;function o(d,e,a={}){const i=document.createElement(d);e&&(i.className=e);for(const[s,f]of Object.entries(a))i.setAttribute(s,f);return i}h(o,"el");function x(d,e){return Number.isFinite(e)?d.int||d.bool?String(Math.round(e)):String(Number(e.toPrecision(6))):""}h(x,"shown");const C=h(d=>Math.round(Math.min(1,Math.max(0,Number.isFinite(d)?d:0))*255),"channel");function L(d){return"#"+[0,1,2].map(e=>C(d[e]).toString(16).padStart(2,"0")).join("")}h(L,"hex");function M(d){const e=parseInt(d.slice(1),16);return[(e>>16&255)/255,(e>>8&255)/255,(e&255)/255]}h(M,"unhex");class P{static{h(this,"ParamPanel")}constructor(e,{write:a,reset:i}){this.root=e,this.write=a,this.reset=i,this.prefix="og-param-"+ ++S+"-",this.rows=new Map,e.classList.add("og-params"),this.clear("")}clear(e){this.rows.clear();const a=o("p","og-params-note");a.textContent=e,this.root.replaceChildren(a)}model({resettable:e,rows:a}){const i=this.#i();this.rows.clear();const s=[];if(!a.length){const t=o("p","og-params-note");t.textContent=N,s.push(t)}let f,c=null;if(a.forEach((t,r)=>{if(t.group===void 0)c=null;else if(c===null||t.group!==f){c=o("fieldset","og-params-group");const n=o("legend");n.textContent=t.group,c.append(n),s.push(c)}f=t.group;const v=this.#s(t,r);c?c.append(v):s.push(v)}),e&&a.length){const t=o("div","og-params-foot"),r=o("button","og-button",{type:"button",title:k});r.textContent="Reset all",r.addEventListener("click",()=>this.reset()),t.append(r),s.push(t)}if(this.root.replaceChildren(...s),i){const t=this.rows.get(i.key),r=t&&t.inputs[i.n];r&&r.el.focus({preventScroll:!0})}}values(e){for(const[a,i]of e){const s=this.rows.get(a);if(!s||i.length!==s.value.length)continue;const f=this.#n(s);s.value=i.map((c,t)=>f.has(t)?s.value[t]:c),this.#t(s)}}#n(e){const a=new Set;for(const i of e.inputs)if(i.el===document.activeElement)for(const s of i.comps)a.add(s);return a}#i(){for(const[e,a]of this.rows){const i=a.inputs.findIndex(s=>s.el===document.activeElement);if(i>=0)return{key:e,n:i}}return null}#t(e){for(const a of e.inputs)a.el!==document.activeElement&&a.refresh()}#e(e,a,i){Number.isFinite(i)&&(e.value[a]=i,this.write(e.row.key,e.value.slice()))}#s(e,a){const i=this.prefix+a,s=o("div","og-param");s.dataset.key=e.key,e.tooltip!==void 0&&(s.title=e.tooltip);const f=o("label","og-param-label",{for:i+"-0"});f.textContent=e.label;const c=o("div","og-param-control"),t={row:e,value:e.value.slice(),inputs:[]};this.rows.set(e.key,t);const r=h((n,l,p)=>t.inputs.push({el:n,comps:l,refresh:p}),"add"),v=h((n,l)=>e.comps>1||l?{"aria-label":e.label+(e.comps>1?" "+y[n]:"")+(l?" "+l:"")}:{},"name");if(e.widget==="checkbox"){const n=o("input",null,{type:"checkbox",id:i+"-0"});n.addEventListener("change",()=>this.#e(t,0,n.checked?1:0)),r(n,[0],()=>{n.checked=t.value[0]!==0&&!Number.isNaN(t.value[0])}),c.append(n)}else if(e.widget==="combo"){const n=o("select",null,{id:i+"-0"});e.choices.forEach((l,p)=>{const u=o("option",null,{value:String(p)});u.textContent=l,n.append(u)}),n.addEventListener("change",()=>this.#e(t,0,Number(n.value))),r(n,[0],()=>{const l=Math.round(t.value[0]);n.selectedIndex=l>=0&&l<e.choices.length?l:-1}),c.append(n)}else if(e.widget==="color"){const n=o("input",null,{type:"color",id:i+"-0"});if(n.addEventListener("input",()=>{const l=M(n.value);for(let p=0;p<3;p++)t.value[p]=l[p];this.write(e.key,t.value.slice())}),r(n,[0,1,2],()=>{n.value=L(t.value)}),c.append(n),e.comps===4){const l=o("input",null,{type:"range",min:"0",max:"1",step:"any","aria-label":e.label+" alpha"});l.addEventListener("input",()=>this.#e(t,3,l.valueAsNumber)),r(l,[3],()=>{l.value=String(t.value[3])}),c.append(l)}}else{const n=e.widget==="slider",l=n?e.int?"1":"any":String(e.step),p={};e.min!==void 0?p.min=String(e.min):e.unsigned&&(p.min="0"),e.max!==void 0&&(p.max=String(e.max));for(let u=0;u<e.comps;u++){const m=n?o("input",null,{type:"range",id:i+"-"+u,step:l,...p,...v(u)}):null,g=o("input","og-param-number",{type:"number",step:l,...p,...n?v(u,"value"):{id:i+"-"+u,...v(u)}});if(g.addEventListener("input",()=>{this.#e(t,u,g.valueAsNumber),m&&(m.value=String(t.value[u]))}),r(g,[u],()=>{g.value=x(e,t.value[u])}),!m){c.append(g);continue}m.addEventListener("input",()=>{this.#e(t,u,m.valueAsNumber),g.value=x(e,t.value[u])}),r(m,[u],()=>{m.value=String(t.value[u])});const b=o("div","og-param-pair");b.append(m,g),c.append(b)}}if(e.tooltip!==void 0)for(const n of t.inputs)n.el.title=e.tooltip;if(s.append(f,c),e.hint!==void 0){const n=o("ul","og-param-hint");for(const l of e.hint){const p=o("li");p.textContent=l,n.append(p)}s.append(n)}return s.addEventListener("focusout",n=>{s.contains(n.relatedTarget)||this.#t(t)}),this.#t(t),s}}export{P as ParamPanel};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/* The player's own look: the box, its bar, the before/after divider. A surface
|
|
2
|
+
restyles it through the custom properties below. */
|
|
3
|
+
|
|
4
|
+
.og-player {
|
|
5
|
+
--og-bar-bg: transparent;
|
|
6
|
+
--og-bar-fg: inherit;
|
|
7
|
+
--og-button-bg: rgba(127, 127, 127, 0.12);
|
|
8
|
+
--og-button-line: rgba(127, 127, 127, 0.35);
|
|
9
|
+
--og-focus: #3d8bfd;
|
|
10
|
+
--og-divider: #ffffff;
|
|
11
|
+
--og-tag-bg: rgba(0, 0, 0, 0.55);
|
|
12
|
+
--og-tag-fg: #ffffff;
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
gap: 8px;
|
|
16
|
+
max-width: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.og-stage {
|
|
20
|
+
position: relative;
|
|
21
|
+
width: 100%;
|
|
22
|
+
background: #000;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
container-type: size;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* The scene at its own shape (--og-aspect, width over height), as large as the
|
|
28
|
+
box allows: the whole box at the box's shape, letterboxed at another. */
|
|
29
|
+
.og-frame {
|
|
30
|
+
position: absolute;
|
|
31
|
+
inset: 0;
|
|
32
|
+
margin: auto;
|
|
33
|
+
width: min(100cqw, 100cqh * var(--og-aspect, 1.7778));
|
|
34
|
+
height: min(100cqh, 100cqw / var(--og-aspect, 1.7778));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.og-screen,
|
|
38
|
+
.og-screen canvas {
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
width: 100%;
|
|
42
|
+
height: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.og-screen canvas {
|
|
46
|
+
display: block;
|
|
47
|
+
outline: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.og-screen canvas:focus-visible {
|
|
51
|
+
outline: 2px solid var(--og-focus);
|
|
52
|
+
outline-offset: -2px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* The poster over the box: the stock desktop, and the still over it, cut at the
|
|
56
|
+
divider. */
|
|
57
|
+
.og-poster,
|
|
58
|
+
.og-poster img {
|
|
59
|
+
position: absolute;
|
|
60
|
+
inset: 0;
|
|
61
|
+
width: 100%;
|
|
62
|
+
height: 100%;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.og-poster[hidden] {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.og-poster img {
|
|
70
|
+
display: block;
|
|
71
|
+
user-select: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.og-poster-before:not([src]) {
|
|
75
|
+
visibility: hidden;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.og-poster-after {
|
|
79
|
+
clip-path: inset(0 0 0 var(--og-split, 0%));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.og-bar {
|
|
83
|
+
display: flex;
|
|
84
|
+
flex-wrap: wrap;
|
|
85
|
+
gap: 8px;
|
|
86
|
+
align-items: center;
|
|
87
|
+
background: var(--og-bar-bg);
|
|
88
|
+
color: var(--og-bar-fg);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.og-button {
|
|
92
|
+
font: inherit;
|
|
93
|
+
padding: 4px 10px;
|
|
94
|
+
border: 1px solid var(--og-button-line);
|
|
95
|
+
border-radius: 6px;
|
|
96
|
+
background: var(--og-button-bg);
|
|
97
|
+
color: inherit;
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.og-button:disabled {
|
|
102
|
+
opacity: 0.5;
|
|
103
|
+
cursor: default;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.og-button[aria-pressed="true"] {
|
|
107
|
+
border-color: var(--og-focus);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.og-button:focus-visible,
|
|
111
|
+
.og-grip:focus-visible {
|
|
112
|
+
outline: 2px solid var(--og-focus);
|
|
113
|
+
outline-offset: 2px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* The divider: a hairline the height of the box with a grip half way down. Its
|
|
117
|
+
hit area is wider than the line, so it can be grabbed. */
|
|
118
|
+
.og-divider {
|
|
119
|
+
position: absolute;
|
|
120
|
+
top: 0;
|
|
121
|
+
bottom: 0;
|
|
122
|
+
width: 24px;
|
|
123
|
+
margin-left: -12px;
|
|
124
|
+
cursor: ew-resize;
|
|
125
|
+
touch-action: none;
|
|
126
|
+
z-index: 1;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.og-divider[hidden] {
|
|
130
|
+
display: none;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.og-divider-line {
|
|
134
|
+
position: absolute;
|
|
135
|
+
top: 0;
|
|
136
|
+
bottom: 0;
|
|
137
|
+
left: 11px;
|
|
138
|
+
width: 2px;
|
|
139
|
+
background: var(--og-divider);
|
|
140
|
+
box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.og-grip {
|
|
144
|
+
position: absolute;
|
|
145
|
+
top: 50%;
|
|
146
|
+
left: 0;
|
|
147
|
+
width: 24px;
|
|
148
|
+
height: 24px;
|
|
149
|
+
margin-top: -12px;
|
|
150
|
+
border-radius: 50%;
|
|
151
|
+
background: var(--og-divider);
|
|
152
|
+
box-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* The two sides' names, at the box's top corners whatever the divider's place. */
|
|
156
|
+
.og-tags {
|
|
157
|
+
position: absolute;
|
|
158
|
+
top: 8px;
|
|
159
|
+
left: 12px;
|
|
160
|
+
pointer-events: none;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.og-tag {
|
|
164
|
+
position: absolute;
|
|
165
|
+
top: 0;
|
|
166
|
+
padding: 2px 6px;
|
|
167
|
+
border-radius: 4px;
|
|
168
|
+
background: var(--og-tag-bg);
|
|
169
|
+
color: var(--og-tag-fg);
|
|
170
|
+
font-size: 12px;
|
|
171
|
+
white-space: nowrap;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.og-tag:first-child {
|
|
175
|
+
right: 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.og-tag:last-child {
|
|
179
|
+
left: 8px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Fullscreen: the box is the screen, and the bar lies over its foot. */
|
|
183
|
+
.og-player:fullscreen {
|
|
184
|
+
display: block;
|
|
185
|
+
background: #000;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.og-player:fullscreen .og-stage {
|
|
189
|
+
position: fixed;
|
|
190
|
+
inset: 0;
|
|
191
|
+
width: auto;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.og-player:fullscreen .og-bar {
|
|
195
|
+
position: fixed;
|
|
196
|
+
left: 0;
|
|
197
|
+
right: 0;
|
|
198
|
+
bottom: 0;
|
|
199
|
+
padding: 10px 16px;
|
|
200
|
+
justify-content: center;
|
|
201
|
+
--og-bar-bg: rgba(0, 0, 0, 0.55);
|
|
202
|
+
--og-bar-fg: #fff;
|
|
203
|
+
z-index: 2;
|
|
204
|
+
transition: opacity 0.2s;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.og-player:fullscreen.og-idle .og-bar {
|
|
208
|
+
opacity: 0;
|
|
209
|
+
pointer-events: none;
|
|
210
|
+
}
|
package/player/player.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*! Overglaze web engine. Licensed under the PolyForm Noncommercial License 1.0.0
|
|
2
|
+
* <https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
3
|
+
* Required Notice: Copyright (c) 2026 Svetlozar Kostadinov
|
|
4
|
+
* With an added permission to run it to develop and preview Overglaze plugins: see LICENSE in @overglaze/web
|
|
5
|
+
*/
|
|
6
|
+
var I=Object.defineProperty;var o=(c,t)=>I(c,"name",{value:t,configurable:!0});import{fill as W}from"./fill.js";const b=[1920,1080],N=["pause","compare","theme","fullscreen"],U=["pause","compare","theme","preset","screen","rotate","wallpaper","fullscreen"],k=["preset","screen","rotate","wallpaper"],d=[[1920,1080],[2560,1440],[3840,2160],[3440,1440]],_="\xD7",j=40,F=3,H=2,V=2500,f=.02,P=.1,y=2;function S(c,t,s){const e=s[0]>1920||s[1]>1080;return c+t+"-"+(e?"3840x2160":"1920x1080")+".png"}o(S,"stockDesktop");const m=o(c=>[Math.max(c[0],c[1]),Math.min(c[0],c[1])],"landscape"),L=o((c,t)=>c[0]===t[0]&&c[1]===t[1],"sameSize");function l(c,t,s={}){const e=document.createElement(c);t&&(e.className=t);for(const[i,h]of Object.entries(s))e.setAttribute(i,h);return e}o(l,"el");class J{static{o(this,"Player")}constructor(t,{plugin:s,modules:e,folder:i,files:h=null,descriptor:r=null,keep:n=null,desktops:a="desktops/",pictures:p=!0,desktop:u="stock",pace:E=y,picture:x=null,poster:g=null,theme:A=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",scene:w=b,controls:C=null,remember:v=null,params:D={},persistParams:M=!1,watchdog:O=!0,clock:z="wall",refreshHz:R=60,minFps:B=j,on:T={}}){this.root=t,this.source={plugin:s,modules:e,folder:i,files:h,descriptor:r,keep:n},this.desktops=a,this.pictures=p!==!1,this.desktopMode=u==="live"?"live":"stock",this.pace=Math.max(1,Math.round(Number(E))||y),this.live=null,this.liveLoad=null,this.liveDirty=!1,this.livePump=null,this.inflight=[],this.customPicture=x,this.theme=A,this.surfaceScene=w,this.windowed=w,this.scene=w,this.remember=typeof v=="string"&&v?v:null,this.pick=this.#k(),this.presets=[],this.wallpapers=[],this.sceneQueue=Promise.resolve(),this.opening=Promise.resolve(),this.params=D,this.persistParams=M,this.watchdog=O,this.clock=z,this.refreshHz=R,this.minFps=B,this.on=T,this.session=null,this.full=!1,this.userPaused=!1,this.inView=!0,this.sessionPaused=!1,this.split=null,this.health={warm:0,slow:0,told:new Set},this.idleTimer=0,this.posterUrls=g,this.stilled=!1,this.#S(C||(this.desktopMode==="live"?U:N)),this.#x(),this.#o(!!g)}load({plugin:t,modules:s,folder:e,files:i=null,descriptor:h=null,keep:r=null,params:n={},poster:a=null}){this.session&&this.session.stop(),this.session=null,this.source={plugin:t,modules:s,folder:e,files:i,descriptor:h,keep:r},this.params=n,this.posterUrls=a,this.stilled=!1,this.#o(!!a),this.#i()}async start(){this.session&&this.session.stop(),this.stilled=!1,this.userPaused=!1,this.sessionPaused=!1,this.health={warm:0,slow:0,told:new Set},this.#i(),await this.#w(),await this.opening;const t=await this.#s(this.scene),s=matchMedia("(prefers-reduced-motion: reduce)").matches,e=this.on,{Session:i}=await import("../engine/session.js");this.session&&this.session.stop(),this.session=new i({box:this.screen,...this.source,picture:t,scene:this.scene,params:this.params,persistParams:this.persistParams,watchdog:this.watchdog,clock:this.clock,refreshHz:this.refreshHz,pointer:[this.scene[0]/2,this.scene[1]/2],hold:s&&this.clock!=="stepped",on:{...e,ready:o(h=>{h.fallback&&this.#c("fallback",h.adapter);const r=this.session.gpuFeatures.filter(n=>!h.features.includes(n));r.length&&this.#c("features",r.join(", ")),e.ready&&e.ready(h)},"ready"),stats:o(h=>{this.#P(h),e.stats&&e.stats(h)},"stats"),held:o(()=>{this.userPaused=!0,this.sessionPaused=!0,this.#i(),e.held&&e.held()},"held"),stopped:o((h,r)=>{h==="unsupported"&&this.#c("unsupported",r),e.stopped&&e.stopped(h,r)},"stopped")}}),this.split!==null&&this.session.split(this.split),this.#l(),await this.session.start()}stop(){this.session&&this.session.stop()}runOn(t){this.session&&this.session.runOn(t)}reveal(){this.#o(!1)}still(){this.session&&this.session.stop(),this.stilled=!0,this.#o(!!this.posterUrls),this.posterUrls&&this.#a(this.surfaceScene),this.#i()}pause(){this.userPaused=!0,this.#l()}resume(){this.userPaused=!1,this.#l()}get paused(){return this.userPaused}async usePicture(t){this.customPicture=t,this.#t(),this.session&&await this.session.setPicture(await this.#s(this.scene))}async setScreen({size:t=this.pick.size,portrait:s=this.pick.portrait}={}){if(!this.live)return;const e=m(t.map(i=>Math.max(1,Math.round(Number(i))||1)));this.pick={...this.pick,size:e,portrait:!!s},this.#n(),this.windowed=this.#p(),this.#t(),this.full||await this.#u(this.windowed)}async setPreset(t){const s=this.presets.find(e=>e.id===t);!this.live||!s||(this.pick={...this.pick,preset:t,wallpaper:s.wallpaper},this.#n(),this.#t(),await this.#r(()=>this.live.setPreset(t)),this.session&&await this.session.setPicture(await this.#s(this.scene)))}resetDesktop(){const t=this.presets[0];this.pick={size:m(this.surfaceScene),portrait:this.surfaceScene[1]>this.surfaceScene[0],preset:t?t.id:null,wallpaper:t?t.wallpaper:null},this.#n(),this.windowed=this.#p(),this.#t();const s=(async()=>{this.full||await this.#u(this.windowed),this.live&&await this.#r(()=>this.live.open({scene:this.scene})),this.session&&await this.session.setPicture(await this.#s(this.scene))})();return this.opening=s.catch(()=>{}),this.opening}async setWallpaper(t){!this.live||!this.wallpapers.some(s=>s.id===t)||(this.pick={...this.pick,wallpaper:t},this.#n(),this.#t(),await this.#r(()=>this.live.setWallpaper(t)),this.session&&await this.session.setPicture(await this.#s(this.scene)))}async setTheme(t){this.theme=t==="dark"?"dark":"light",this.#m(),this.#d(),this.live&&await this.#r(()=>this.live.setTheme(this.theme)),this.session&&await this.session.setPicture(await this.#s(this.scene)),this.#e("theme",this.theme)}compare(t){this.split=t===null?null:Math.min(1,Math.max(0,t));const s=this.split!==null;if(this.divider.hidden=!s,this.buttons.compare&&this.buttons.compare.setAttribute("aria-pressed",String(s)),s){const e=Math.round(this.split*100);this.divider.style.left=this.split*100+"%",this.grip.setAttribute("aria-valuenow",String(e)),this.grip.setAttribute("aria-valuetext",e+"% before, "+(100-e)+"% after")}this.poster.style.setProperty("--og-split",s?this.split*100+"%":"0%"),this.#d(),this.session&&this.session.split(this.split),this.#e("split",this.split)}fullscreen(){document.fullscreenElement===this.root?document.exitFullscreen():this.root.requestFullscreen().catch(()=>{})}async#s(t){if(this.customPicture){const i=this.customPicture;return typeof i=="function"?i({theme:this.theme,scene:t}):i}if(this.live&&(this.live.scene[0]!==t[0]||this.live.scene[1]!==t[1])&&await this.#r(()=>this.live.setScene(t)),this.live)try{return this.live.render()}catch(i){this.#h(i)}if(!this.pictures){const i=W(this.theme,t[0],t[1]);return new ImageData(i.data,i.width,i.height)}const s=S(this.desktops,this.theme,t),e=await fetch(s);if(!e.ok)throw new Error("no stock desktop at "+s+" ("+e.status+")");return e.blob()}#w(){return this.desktopMode!=="live"||this.live?Promise.resolve():(this.liveLoad||(this.liveLoad=(async()=>{try{const t=new URL(this.desktops,location.href),{Desktop:s,PRESETS:e,WALLPAPERS:i}=await import(new URL("desktop.js",t).href);this.presets=e,this.wallpapers=i;const h=e.find(a=>a.id===this.pick.preset)||e[0];this.pick.preset=h.id,i.some(a=>a.id===this.pick.wallpaper)||(this.pick.wallpaper=h.wallpaper);const r=this.#p(),n=new s({theme:this.theme,scene:this.full?this.scene:r,preset:this.pick.preset,wallpaper:this.pick.wallpaper});await n.ready(),this.live=n,this.windowed=r,this.full||(this.scene=r,this.#a()),this.#L(),this.#t(),this.#v(),this.#e("desktop","live","")}catch(t){this.#h(t)}})()),this.liveLoad)}async#r(t){try{await t()}catch(s){this.#h(s)}}#h(t){this.live=null,this.desktopMode="stock",this.screen.style.cursor="",this.#t(),this.#e("desktop",this.pictures?"stock":"fill",String(t&&t.message||t))}#v(){if(this.pointerWired)return;this.pointerWired=!0;let t=!1,s=!1;const e=o((i,h)=>{const r=this.live;if(!r||this.customPicture)return;const n=this.screen.getBoundingClientRect();if(!n.width||!n.height)return;const a=(h.clientX-n.left)/n.width,p=(h.clientY-n.top)/n.height;if(i==="down"){if(h.button!==0)return;const u=this.session;if(s=!!(u&&u.claims(a*this.scene[0],p*this.scene[1])),t=!0,s)return}else if(s){(i==="up"||i==="leave")&&(s=t=!1);return}else if(i==="up"){if(!t)return;t=!1}else if(i==="leave"&&t)return;r.pointer(i,a*r.size[0],p*r.size[1])&&this.#g(),this.screen.style.cursor=r.cursor},"feed");this.screen.addEventListener("pointerdown",i=>e("down",i)),this.screen.addEventListener("pointermove",i=>e("move",i)),this.screen.addEventListener("pointerup",i=>e("up",i)),this.screen.addEventListener("pointercancel",i=>e("up",i)),this.screen.addEventListener("pointerleave",i=>e("leave",i))}#g(){this.liveDirty=!0,this.livePump||(this.livePump=this.#b().finally(()=>this.livePump=null))}async#b(){for(;this.liveDirty&&this.live;){const t=this.session;for(;this.inflight.length>=this.pace;)await this.inflight.shift();if(!this.liveDirty||!this.live)break;this.liveDirty=!1;let s;try{s=this.live.render()}catch(e){this.#h(e);break}!t||t!==this.session||(await t.setPicture(s),this.inflight.push(t.pictureIn()))}}#k(){let t=null;try{t=this.remember?JSON.parse(localStorage.getItem(this.remember)||"null"):null}catch{t=null}const s=m(this.surfaceScene);return{size:(t&&Array.isArray(t.size)?[...d,s].find(i=>L(i,t.size)):null)||s,portrait:t&&typeof t.portrait=="boolean"?t.portrait:this.surfaceScene[1]>this.surfaceScene[0],preset:t&&typeof t.preset=="string"?t.preset:null,wallpaper:t&&typeof t.wallpaper=="string"?t.wallpaper:null}}#n(){if(this.remember)try{localStorage.setItem(this.remember,JSON.stringify(this.pick))}catch{}}#p(){const[t,s]=this.pick.size;return this.pick.portrait?[s,t]:[t,s]}#u(t){const s=this.sceneQueue.then(async()=>{this.scene=t,this.#a(),this.session&&(await this.session.resize(t,await this.#s(t)),this.inflight=[])});return this.sceneQueue=s.catch(()=>{}),s}#a(t=this.scene){this.frame.style.setProperty("--og-aspect",String(t[0]/t[1]))}#o(t){this.poster.hidden=!t,this.#d(),this.#t()}#d(){const t=this.posterUrls;if(!t||this.poster.hidden)return;const s=new URL(t[this.theme],location.href).href;if(this.posterAfter.src!==s&&(this.posterAfter.src=s),this.posterAfter.alt=t.alt||"",this.split===null||!this.pictures)return;const e=new URL(S(this.desktops,this.theme,b),location.href).href;this.posterBefore.src!==e&&(this.posterBefore.src=e)}#l(){const t=this.userPaused||!this.inView;this.session&&t!==this.sessionPaused&&(t?this.session.pause():(this.health.warm=0,this.session.resume())),this.sessionPaused=t,this.#i()}#i(){const t=this.buttons&&this.buttons.pause;t&&(t.textContent=this.userPaused?"Play":"Pause",t.setAttribute("aria-label",this.userPaused?"Play the effect":"Pause the effect"),t.hidden=this.stilled),this.root.classList.toggle("og-paused",this.userPaused),this.#e("paused",this.userPaused)}#P(t){const s=this.health;if(this.sessionPaused||document.hidden||!this.session||this.session.phase!=="running"){s.warm=0;return}if(s.warm<H){s.warm++;return}s.slow=t.fps<this.minFps?s.slow+1:0,s.slow>=F&&this.#c("slow",t.fps)}#c(t,s){this.health.told.has(t)||(this.health.told.add(t),this.#e("degraded",t,s))}async#y(){const t=document.fullscreenElement===this.root;if(t===this.full)return;this.full=t,this.#m(),this.#t();const s=t?[Math.round(screen.width*devicePixelRatio),Math.round(screen.height*devicePixelRatio)]:this.windowed;this.stage.style.aspectRatio=t?"":this.surfaceScene[0]+" / "+this.surfaceScene[1],await this.#u(s);const e=this.screen.querySelector("canvas");this.session&&t&&e&&e.focus({preventScroll:!0}),this.#f(),this.#e("fullscreen",t)}#f(){this.root.classList.remove("og-idle"),clearTimeout(this.idleTimer),this.full&&(this.idleTimer=setTimeout(()=>{this.bar.contains(document.activeElement)||this.root.classList.add("og-idle")},V))}#S(t){const s=this.root;s.classList.add("og-player"),this.stage=l("div","og-stage"),this.stage.style.aspectRatio=this.scene[0]+" / "+this.scene[1],this.frame=l("div","og-frame"),this.screen=l("div","og-screen"),this.divider=l("div","og-divider"),this.divider.hidden=!0,this.grip=l("div","og-grip",{role:"slider",tabindex:"0","aria-label":"Before and after","aria-valuemin":"0","aria-valuemax":"100"}),this.divider.append(l("div","og-divider-line"),this.grip);const e=l("div","og-tags");e.append(Object.assign(l("span","og-tag"),{textContent:"Before"}),Object.assign(l("span","og-tag"),{textContent:"After"})),this.divider.append(e),this.poster=l("div","og-poster"),this.posterBefore=l("img","og-poster-before",{alt:"",draggable:"false"}),this.posterAfter=l("img","og-poster-after",{alt:"",draggable:"false"}),this.poster.append(this.posterBefore,this.posterAfter),this.frame.append(this.screen,this.poster,this.divider),this.stage.append(this.frame),this.#a(),this.bar=l("div","og-bar"),this.buttons={};const i={pause:o(()=>this.userPaused?this.resume():this.pause(),"pause"),compare:o(()=>this.compare(this.split===null?.5:null),"compare"),theme:o(()=>this.setTheme(this.theme==="dark"?"light":"dark"),"theme"),fullscreen:o(()=>this.fullscreen(),"fullscreen"),rotate:o(()=>this.setScreen({portrait:!this.pick.portrait}),"rotate")},h={preset:["Desktop",r=>this.setPreset(r)],screen:["Screen size",r=>this.setScreen({size:r.split("x").map(Number)})],wallpaper:["Wallpaper",r=>this.setWallpaper(r)]};for(const r of t){let n;if(h[r]){const[a,p]=h[r];n=l("select","og-button og-select",{"data-control":r,"aria-label":a}),n.addEventListener("change",()=>p(n.value))}else if(i[r])n=l("button","og-button",{type:"button","data-control":r}),n.addEventListener("click",i[r]);else continue;k.includes(r)&&(n.hidden=!0),this.buttons[r]=n,this.bar.append(n)}if(this.buttons.screen){const r=m(this.surfaceScene),n=d.some(a=>L(a,r))?d:[...d,r];for(const[a,p]of n)this.buttons.screen.append(Object.assign(l("option","",{value:a+"x"+p}),{textContent:a+_+p}))}this.buttons.compare&&this.buttons.compare.setAttribute("aria-pressed","false"),s.replaceChildren(this.stage,this.bar),this.#m(),this.#i(),this.#E()}#m(){const t=this.buttons;if(t.compare&&(t.compare.textContent="Before/after"),t.theme){const s=this.theme==="dark"?"light":"dark";t.theme.textContent=s==="dark"?"Dark desktop":"Light desktop",t.theme.setAttribute("aria-label","Show the "+s+" desktop")}t.fullscreen&&(t.fullscreen.textContent=this.full?"Exit fullscreen":"Fullscreen")}#L(){for(const[t,s]of[["preset",this.presets],["wallpaper",this.wallpapers]]){const e=this.buttons[t];e&&e.replaceChildren(...s.map(({id:i,name:h})=>Object.assign(l("option","",{value:i}),{textContent:h})))}}#t(){const t=this.buttons,s=!!this.live&&!this.customPicture&&this.poster.hidden;for(const e of k)t[e]&&(t[e].hidden=!s);if(t.screen&&(t.screen.value=this.pick.size.join("x"),t.screen.disabled=this.full),t.rotate){const e=this.pick.portrait?"landscape":"portrait";t.rotate.textContent=e==="portrait"?"Portrait":"Landscape",t.rotate.setAttribute("aria-label","Turn the screen to "+e),t.rotate.disabled=this.full}t.preset&&this.live&&(t.preset.value=this.pick.preset),t.wallpaper&&this.live&&(t.wallpaper.value=this.pick.wallpaper)}#E(){const t=o(s=>{const e=this.frame.getBoundingClientRect();return(s.clientX-e.left)/e.width},"at");this.divider.addEventListener("pointerdown",s=>{s.button===0&&(s.preventDefault(),this.divider.setPointerCapture(s.pointerId),this.grip.focus({preventScroll:!0}),this.compare(t(s)))}),this.divider.addEventListener("pointermove",s=>{this.divider.hasPointerCapture(s.pointerId)&&this.compare(t(s))}),this.grip.addEventListener("keydown",s=>{const e={ArrowLeft:-f,ArrowDown:-f,ArrowRight:f,ArrowUp:f,PageDown:-P,PageUp:P};let i=null;s.key in e?i=this.split+e[s.key]:s.key==="Home"?i=0:s.key==="End"&&(i=1),i!==null&&(s.preventDefault(),this.compare(i))})}#x(){new IntersectionObserver(t=>{const s=t[t.length-1];this.inView=s.isIntersecting,this.#l()}).observe(this.stage),document.addEventListener("fullscreenchange",()=>this.#y()),this.root.addEventListener("pointermove",()=>this.#f()),this.root.addEventListener("focusin",()=>this.#f())}#e(t,...s){const e=this.on[t];e&&e(...s)}}export{J as Player,S as stockDesktop};
|