mirror of
				https://github.com/D4M13N-D3V/godot_grid_inventory.git
				synced 2025-11-04 03:25:44 +00:00 
			
		
		
		
	UPDATE GITHUB PAGES 7e011ad0b2ea51671bd8f55d99f1579829177370
This commit is contained in:
		
						commit
						6b34ca79a0
					
				
							
								
								
									
										146
									
								
								coi-serviceworker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								coi-serviceworker.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
 | 
			
		||||
let coepCredentialless = false;
 | 
			
		||||
if (typeof window === 'undefined') {
 | 
			
		||||
    self.addEventListener("install", () => self.skipWaiting());
 | 
			
		||||
    self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
 | 
			
		||||
 | 
			
		||||
    self.addEventListener("message", (ev) => {
 | 
			
		||||
        if (!ev.data) {
 | 
			
		||||
            return;
 | 
			
		||||
        } else if (ev.data.type === "deregister") {
 | 
			
		||||
            self.registration
 | 
			
		||||
                .unregister()
 | 
			
		||||
                .then(() => {
 | 
			
		||||
                    return self.clients.matchAll();
 | 
			
		||||
                })
 | 
			
		||||
                .then(clients => {
 | 
			
		||||
                    clients.forEach((client) => client.navigate(client.url));
 | 
			
		||||
                });
 | 
			
		||||
        } else if (ev.data.type === "coepCredentialless") {
 | 
			
		||||
            coepCredentialless = ev.data.value;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    self.addEventListener("fetch", function (event) {
 | 
			
		||||
        const r = event.request;
 | 
			
		||||
        if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const request = (coepCredentialless && r.mode === "no-cors")
 | 
			
		||||
            ? new Request(r, {
 | 
			
		||||
                credentials: "omit",
 | 
			
		||||
            })
 | 
			
		||||
            : r;
 | 
			
		||||
        event.respondWith(
 | 
			
		||||
            fetch(request)
 | 
			
		||||
                .then((response) => {
 | 
			
		||||
                    if (response.status === 0) {
 | 
			
		||||
                        return response;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    const newHeaders = new Headers(response.headers);
 | 
			
		||||
                    newHeaders.set("Cross-Origin-Embedder-Policy",
 | 
			
		||||
                        coepCredentialless ? "credentialless" : "require-corp"
 | 
			
		||||
                    );
 | 
			
		||||
                    if (!coepCredentialless) {
 | 
			
		||||
                        newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
 | 
			
		||||
                    }
 | 
			
		||||
                    newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
 | 
			
		||||
 | 
			
		||||
                    return new Response(response.body, {
 | 
			
		||||
                        status: response.status,
 | 
			
		||||
                        statusText: response.statusText,
 | 
			
		||||
                        headers: newHeaders,
 | 
			
		||||
                    });
 | 
			
		||||
                })
 | 
			
		||||
                .catch((e) => console.error(e))
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
} else {
 | 
			
		||||
    (() => {
 | 
			
		||||
        const reloadedBySelf = window.sessionStorage.getItem("coiReloadedBySelf");
 | 
			
		||||
        window.sessionStorage.removeItem("coiReloadedBySelf");
 | 
			
		||||
        const coepDegrading = (reloadedBySelf == "coepdegrade");
 | 
			
		||||
 | 
			
		||||
        // You can customize the behavior of this script through a global `coi` variable.
 | 
			
		||||
        const coi = {
 | 
			
		||||
            shouldRegister: () => !reloadedBySelf,
 | 
			
		||||
            shouldDeregister: () => false,
 | 
			
		||||
            coepCredentialless: () => true,
 | 
			
		||||
            coepDegrade: () => true,
 | 
			
		||||
            doReload: () => window.location.reload(),
 | 
			
		||||
            quiet: false,
 | 
			
		||||
            ...window.coi
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const n = navigator;
 | 
			
		||||
        const controlling = n.serviceWorker && n.serviceWorker.controller;
 | 
			
		||||
 | 
			
		||||
        // Record the failure if the page is served by serviceWorker.
 | 
			
		||||
        if (controlling && !window.crossOriginIsolated) {
 | 
			
		||||
            window.sessionStorage.setItem("coiCoepHasFailed", "true");
 | 
			
		||||
        }
 | 
			
		||||
        const coepHasFailed = window.sessionStorage.getItem("coiCoepHasFailed");
 | 
			
		||||
 | 
			
		||||
        if (controlling) {
 | 
			
		||||
            // Reload only on the first failure.
 | 
			
		||||
            const reloadToDegrade = coi.coepDegrade() && !(
 | 
			
		||||
                coepDegrading || window.crossOriginIsolated
 | 
			
		||||
            );
 | 
			
		||||
            n.serviceWorker.controller.postMessage({
 | 
			
		||||
                type: "coepCredentialless",
 | 
			
		||||
                value: (reloadToDegrade || coepHasFailed && coi.coepDegrade())
 | 
			
		||||
                    ? false
 | 
			
		||||
                    : coi.coepCredentialless(),
 | 
			
		||||
            });
 | 
			
		||||
            if (reloadToDegrade) {
 | 
			
		||||
                !coi.quiet && console.log("Reloading page to degrade COEP.");
 | 
			
		||||
                window.sessionStorage.setItem("coiReloadedBySelf", "coepdegrade");
 | 
			
		||||
                coi.doReload("coepdegrade");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (coi.shouldDeregister()) {
 | 
			
		||||
                n.serviceWorker.controller.postMessage({ type: "deregister" });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
 | 
			
		||||
        // already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
 | 
			
		||||
        if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
 | 
			
		||||
 | 
			
		||||
        if (!window.isSecureContext) {
 | 
			
		||||
            !coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // In some environments (e.g. Firefox private mode) this won't be available
 | 
			
		||||
        if (!n.serviceWorker) {
 | 
			
		||||
            !coi.quiet && console.error("COOP/COEP Service Worker not registered, perhaps due to private mode.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        n.serviceWorker.register(window.document.currentScript.src).then(
 | 
			
		||||
            (registration) => {
 | 
			
		||||
                !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
 | 
			
		||||
 | 
			
		||||
                registration.addEventListener("updatefound", () => {
 | 
			
		||||
                    !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
 | 
			
		||||
                    window.sessionStorage.setItem("coiReloadedBySelf", "updatefound");
 | 
			
		||||
                    coi.doReload();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // If the registration is active, but it's not controlling the page
 | 
			
		||||
                if (registration.active && !n.serviceWorker.controller) {
 | 
			
		||||
                    !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
 | 
			
		||||
                    window.sessionStorage.setItem("coiReloadedBySelf", "notcontrolling");
 | 
			
		||||
                    coi.doReload();
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            (err) => {
 | 
			
		||||
                !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    })();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								index.apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								index.apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										213
									
								
								index.audio.worklet.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								index.audio.worklet.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,213 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*  audio.worklet.js                                                      */
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*                         This file is part of:                          */
 | 
			
		||||
/*                             GODOT ENGINE                               */
 | 
			
		||||
/*                        https://godotengine.org                         */
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
 | 
			
		||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
 | 
			
		||||
/*                                                                        */
 | 
			
		||||
/* Permission is hereby granted, free of charge, to any person obtaining  */
 | 
			
		||||
/* a copy of this software and associated documentation files (the        */
 | 
			
		||||
/* "Software"), to deal in the Software without restriction, including    */
 | 
			
		||||
/* without limitation the rights to use, copy, modify, merge, publish,    */
 | 
			
		||||
/* distribute, sublicense, and/or sell copies of the Software, and to     */
 | 
			
		||||
/* permit persons to whom the Software is furnished to do so, subject to  */
 | 
			
		||||
/* the following conditions:                                              */
 | 
			
		||||
/*                                                                        */
 | 
			
		||||
/* The above copyright notice and this permission notice shall be         */
 | 
			
		||||
/* included in all copies or substantial portions of the Software.        */
 | 
			
		||||
/*                                                                        */
 | 
			
		||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
 | 
			
		||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
 | 
			
		||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
 | 
			
		||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
 | 
			
		||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
 | 
			
		||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
 | 
			
		||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
class RingBuffer {
 | 
			
		||||
	constructor(p_buffer, p_state, p_threads) {
 | 
			
		||||
		this.buffer = p_buffer;
 | 
			
		||||
		this.avail = p_state;
 | 
			
		||||
		this.threads = p_threads;
 | 
			
		||||
		this.rpos = 0;
 | 
			
		||||
		this.wpos = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data_left() {
 | 
			
		||||
		return this.threads ? Atomics.load(this.avail, 0) : this.avail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	space_left() {
 | 
			
		||||
		return this.buffer.length - this.data_left();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	read(output) {
 | 
			
		||||
		const size = this.buffer.length;
 | 
			
		||||
		let from = 0;
 | 
			
		||||
		let to_write = output.length;
 | 
			
		||||
		if (this.rpos + to_write > size) {
 | 
			
		||||
			const high = size - this.rpos;
 | 
			
		||||
			output.set(this.buffer.subarray(this.rpos, size));
 | 
			
		||||
			from = high;
 | 
			
		||||
			to_write -= high;
 | 
			
		||||
			this.rpos = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (to_write) {
 | 
			
		||||
			output.set(this.buffer.subarray(this.rpos, this.rpos + to_write), from);
 | 
			
		||||
		}
 | 
			
		||||
		this.rpos += to_write;
 | 
			
		||||
		if (this.threads) {
 | 
			
		||||
			Atomics.add(this.avail, 0, -output.length);
 | 
			
		||||
			Atomics.notify(this.avail, 0);
 | 
			
		||||
		} else {
 | 
			
		||||
			this.avail -= output.length;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	write(p_buffer) {
 | 
			
		||||
		const to_write = p_buffer.length;
 | 
			
		||||
		const mw = this.buffer.length - this.wpos;
 | 
			
		||||
		if (mw >= to_write) {
 | 
			
		||||
			this.buffer.set(p_buffer, this.wpos);
 | 
			
		||||
			this.wpos += to_write;
 | 
			
		||||
			if (mw === to_write) {
 | 
			
		||||
				this.wpos = 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			const high = p_buffer.subarray(0, mw);
 | 
			
		||||
			const low = p_buffer.subarray(mw);
 | 
			
		||||
			this.buffer.set(high, this.wpos);
 | 
			
		||||
			this.buffer.set(low);
 | 
			
		||||
			this.wpos = low.length;
 | 
			
		||||
		}
 | 
			
		||||
		if (this.threads) {
 | 
			
		||||
			Atomics.add(this.avail, 0, to_write);
 | 
			
		||||
			Atomics.notify(this.avail, 0);
 | 
			
		||||
		} else {
 | 
			
		||||
			this.avail += to_write;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class GodotProcessor extends AudioWorkletProcessor {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.threads = false;
 | 
			
		||||
		this.running = true;
 | 
			
		||||
		this.lock = null;
 | 
			
		||||
		this.notifier = null;
 | 
			
		||||
		this.output = null;
 | 
			
		||||
		this.output_buffer = new Float32Array();
 | 
			
		||||
		this.input = null;
 | 
			
		||||
		this.input_buffer = new Float32Array();
 | 
			
		||||
		this.port.onmessage = (event) => {
 | 
			
		||||
			const cmd = event.data['cmd'];
 | 
			
		||||
			const data = event.data['data'];
 | 
			
		||||
			this.parse_message(cmd, data);
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	process_notify() {
 | 
			
		||||
		if (this.notifier) {
 | 
			
		||||
			Atomics.add(this.notifier, 0, 1);
 | 
			
		||||
			Atomics.notify(this.notifier, 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parse_message(p_cmd, p_data) {
 | 
			
		||||
		if (p_cmd === 'start' && p_data) {
 | 
			
		||||
			const state = p_data[0];
 | 
			
		||||
			let idx = 0;
 | 
			
		||||
			this.threads = true;
 | 
			
		||||
			this.lock = state.subarray(idx, ++idx);
 | 
			
		||||
			this.notifier = state.subarray(idx, ++idx);
 | 
			
		||||
			const avail_in = state.subarray(idx, ++idx);
 | 
			
		||||
			const avail_out = state.subarray(idx, ++idx);
 | 
			
		||||
			this.input = new RingBuffer(p_data[1], avail_in, true);
 | 
			
		||||
			this.output = new RingBuffer(p_data[2], avail_out, true);
 | 
			
		||||
		} else if (p_cmd === 'stop') {
 | 
			
		||||
			this.running = false;
 | 
			
		||||
			this.output = null;
 | 
			
		||||
			this.input = null;
 | 
			
		||||
			this.lock = null;
 | 
			
		||||
			this.notifier = null;
 | 
			
		||||
		} else if (p_cmd === 'start_nothreads') {
 | 
			
		||||
			this.output = new RingBuffer(p_data[0], p_data[0].length, false);
 | 
			
		||||
		} else if (p_cmd === 'chunk') {
 | 
			
		||||
			this.output.write(p_data);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static array_has_data(arr) {
 | 
			
		||||
		return arr.length && arr[0].length && arr[0][0].length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	process(inputs, outputs, parameters) {
 | 
			
		||||
		if (!this.running) {
 | 
			
		||||
			return false; // Stop processing.
 | 
			
		||||
		}
 | 
			
		||||
		if (this.output === null) {
 | 
			
		||||
			return true; // Not ready yet, keep processing.
 | 
			
		||||
		}
 | 
			
		||||
		const process_input = GodotProcessor.array_has_data(inputs);
 | 
			
		||||
		if (process_input) {
 | 
			
		||||
			const input = inputs[0];
 | 
			
		||||
			const chunk = input[0].length * input.length;
 | 
			
		||||
			if (this.input_buffer.length !== chunk) {
 | 
			
		||||
				this.input_buffer = new Float32Array(chunk);
 | 
			
		||||
			}
 | 
			
		||||
			if (!this.threads) {
 | 
			
		||||
				GodotProcessor.write_input(this.input_buffer, input);
 | 
			
		||||
				this.port.postMessage({ 'cmd': 'input', 'data': this.input_buffer });
 | 
			
		||||
			} else if (this.input.space_left() >= chunk) {
 | 
			
		||||
				GodotProcessor.write_input(this.input_buffer, input);
 | 
			
		||||
				this.input.write(this.input_buffer);
 | 
			
		||||
			} else {
 | 
			
		||||
				this.port.postMessage('Input buffer is full! Skipping input frame.');
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		const process_output = GodotProcessor.array_has_data(outputs);
 | 
			
		||||
		if (process_output) {
 | 
			
		||||
			const output = outputs[0];
 | 
			
		||||
			const chunk = output[0].length * output.length;
 | 
			
		||||
			if (this.output_buffer.length !== chunk) {
 | 
			
		||||
				this.output_buffer = new Float32Array(chunk);
 | 
			
		||||
			}
 | 
			
		||||
			if (this.output.data_left() >= chunk) {
 | 
			
		||||
				this.output.read(this.output_buffer);
 | 
			
		||||
				GodotProcessor.write_output(output, this.output_buffer);
 | 
			
		||||
				if (!this.threads) {
 | 
			
		||||
					this.port.postMessage({ 'cmd': 'read', 'data': chunk });
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				this.port.postMessage('Output buffer has not enough frames! Skipping output frame.');
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		this.process_notify();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static write_output(dest, source) {
 | 
			
		||||
		const channels = dest.length;
 | 
			
		||||
		for (let ch = 0; ch < channels; ch++) {
 | 
			
		||||
			for (let sample = 0; sample < dest[ch].length; sample++) {
 | 
			
		||||
				dest[ch][sample] = source[sample * channels + ch];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static write_input(dest, source) {
 | 
			
		||||
		const channels = source.length;
 | 
			
		||||
		for (let ch = 0; ch < channels; ch++) {
 | 
			
		||||
			for (let sample = 0; sample < source[ch].length; sample++) {
 | 
			
		||||
				dest[sample * channels + ch] = source[ch][sample];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
registerProcessor('godot-processor', GodotProcessor);
 | 
			
		||||
							
								
								
									
										249
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,249 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<script src="coi-serviceworker.js"></script>
 | 
			
		||||
	<head>
 | 
			
		||||
		<meta charset="utf-8">
 | 
			
		||||
		<meta name="viewport" content="width=device-width, user-scalable=no">
 | 
			
		||||
		<title>Grid Inventory System</title>
 | 
			
		||||
		<style>
 | 
			
		||||
body {
 | 
			
		||||
	touch-action: none;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	border: 0 none;
 | 
			
		||||
	padding: 0;
 | 
			
		||||
	text-align: center;
 | 
			
		||||
	background-color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#canvas {
 | 
			
		||||
	display: block;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#canvas:focus {
 | 
			
		||||
	outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.godot {
 | 
			
		||||
	font-family: 'Noto Sans', 'Droid Sans', Arial, sans-serif;
 | 
			
		||||
	color: #e0e0e0;
 | 
			
		||||
	background-color: #3b3943;
 | 
			
		||||
	background-image: linear-gradient(to bottom, #403e48, #35333c);
 | 
			
		||||
	border: 1px solid #45434e;
 | 
			
		||||
	box-shadow: 0 0 1px 1px #2f2d35;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Status display */
 | 
			
		||||
 | 
			
		||||
#status {
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	left: 0;
 | 
			
		||||
	top: 0;
 | 
			
		||||
	right: 0;
 | 
			
		||||
	bottom: 0;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	justify-content: center;
 | 
			
		||||
	align-items: center;
 | 
			
		||||
	/* don't consume click events - make children visible explicitly */
 | 
			
		||||
	visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#status-progress {
 | 
			
		||||
	width: 366px;
 | 
			
		||||
	height: 7px;
 | 
			
		||||
	background-color: #38363A;
 | 
			
		||||
	border: 1px solid #444246;
 | 
			
		||||
	padding: 1px;
 | 
			
		||||
	box-shadow: 0 0 2px 1px #1B1C22;
 | 
			
		||||
	border-radius: 2px;
 | 
			
		||||
	visibility: visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (orientation:portrait) {
 | 
			
		||||
	#status-progress {
 | 
			
		||||
		width: 61.8%;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#status-progress-inner {
 | 
			
		||||
	height: 100%;
 | 
			
		||||
	width: 0;
 | 
			
		||||
	box-sizing: border-box;
 | 
			
		||||
	transition: width 0.5s linear;
 | 
			
		||||
	background-color: #202020;
 | 
			
		||||
	border: 1px solid #222223;
 | 
			
		||||
	box-shadow: 0 0 1px 1px #27282E;
 | 
			
		||||
	border-radius: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#status-indeterminate {
 | 
			
		||||
	height: 42px;
 | 
			
		||||
	visibility: visible;
 | 
			
		||||
	position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#status-indeterminate > div {
 | 
			
		||||
	width: 4.5px;
 | 
			
		||||
	height: 0;
 | 
			
		||||
	border-style: solid;
 | 
			
		||||
	border-width: 9px 3px 0 3px;
 | 
			
		||||
	border-color: #2b2b2b transparent transparent transparent;
 | 
			
		||||
	transform-origin: center 21px;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#status-indeterminate > div:nth-child(1) { transform: rotate( 22.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(2) { transform: rotate( 67.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(3) { transform: rotate(112.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(4) { transform: rotate(157.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(5) { transform: rotate(202.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(6) { transform: rotate(247.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(7) { transform: rotate(292.5deg); }
 | 
			
		||||
#status-indeterminate > div:nth-child(8) { transform: rotate(337.5deg); }
 | 
			
		||||
 | 
			
		||||
#status-notice {
 | 
			
		||||
	margin: 0 100px;
 | 
			
		||||
	line-height: 1.3;
 | 
			
		||||
	visibility: visible;
 | 
			
		||||
	padding: 4px 6px;
 | 
			
		||||
	visibility: visible;
 | 
			
		||||
}
 | 
			
		||||
		</style>
 | 
			
		||||
		<link id='-gd-engine-icon' rel='icon' type='image/png' href='index.icon.png' />
 | 
			
		||||
<link rel='apple-touch-icon' href='index.apple-touch-icon.png'/>
 | 
			
		||||
 | 
			
		||||
	</head>
 | 
			
		||||
	<body>
 | 
			
		||||
		<canvas id="canvas">
 | 
			
		||||
			HTML5 canvas appears to be unsupported in the current browser.<br >
 | 
			
		||||
			Please try updating or use a different browser.
 | 
			
		||||
		</canvas>
 | 
			
		||||
		<div id="status">
 | 
			
		||||
			<div id="status-progress" style="display: none;" oncontextmenu="event.preventDefault();">
 | 
			
		||||
				<div id ="status-progress-inner"></div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div id="status-indeterminate" style="display: none;" oncontextmenu="event.preventDefault();">
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
				<div></div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div id="status-notice" class="godot" style="display: none;"></div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<script src="index.js"></script>
 | 
			
		||||
		<script>
 | 
			
		||||
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"executable":"index","experimentalVK":false,"fileSizes":{"index.pck":39845520,"index.wasm":35649444},"focusCanvas":true,"gdextensionLibs":[]};
 | 
			
		||||
const engine = new Engine(GODOT_CONFIG);
 | 
			
		||||
 | 
			
		||||
(function () {
 | 
			
		||||
	const INDETERMINATE_STATUS_STEP_MS = 100;
 | 
			
		||||
	const statusProgress = document.getElementById('status-progress');
 | 
			
		||||
	const statusProgressInner = document.getElementById('status-progress-inner');
 | 
			
		||||
	const statusIndeterminate = document.getElementById('status-indeterminate');
 | 
			
		||||
	const statusNotice = document.getElementById('status-notice');
 | 
			
		||||
 | 
			
		||||
	let initializing = true;
 | 
			
		||||
	let statusMode = 'hidden';
 | 
			
		||||
 | 
			
		||||
	let animationCallbacks = [];
 | 
			
		||||
	function animate(time) {
 | 
			
		||||
		animationCallbacks.forEach((callback) => callback(time));
 | 
			
		||||
		requestAnimationFrame(animate);
 | 
			
		||||
	}
 | 
			
		||||
	requestAnimationFrame(animate);
 | 
			
		||||
 | 
			
		||||
	function animateStatusIndeterminate(ms) {
 | 
			
		||||
		const i = Math.floor((ms / INDETERMINATE_STATUS_STEP_MS) % 8);
 | 
			
		||||
		if (statusIndeterminate.children[i].style.borderTopColor === '') {
 | 
			
		||||
			Array.prototype.slice.call(statusIndeterminate.children).forEach((child) => {
 | 
			
		||||
				child.style.borderTopColor = '';
 | 
			
		||||
			});
 | 
			
		||||
			statusIndeterminate.children[i].style.borderTopColor = '#dfdfdf';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function setStatusMode(mode) {
 | 
			
		||||
		if (statusMode === mode || !initializing) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		[statusProgress, statusIndeterminate, statusNotice].forEach((elem) => {
 | 
			
		||||
			elem.style.display = 'none';
 | 
			
		||||
		});
 | 
			
		||||
		animationCallbacks = animationCallbacks.filter(function (value) {
 | 
			
		||||
			return (value !== animateStatusIndeterminate);
 | 
			
		||||
		});
 | 
			
		||||
		switch (mode) {
 | 
			
		||||
		case 'progress':
 | 
			
		||||
			statusProgress.style.display = 'block';
 | 
			
		||||
			break;
 | 
			
		||||
		case 'indeterminate':
 | 
			
		||||
			statusIndeterminate.style.display = 'block';
 | 
			
		||||
			animationCallbacks.push(animateStatusIndeterminate);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'notice':
 | 
			
		||||
			statusNotice.style.display = 'block';
 | 
			
		||||
			break;
 | 
			
		||||
		case 'hidden':
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			throw new Error('Invalid status mode');
 | 
			
		||||
		}
 | 
			
		||||
		statusMode = mode;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function setStatusNotice(text) {
 | 
			
		||||
		while (statusNotice.lastChild) {
 | 
			
		||||
			statusNotice.removeChild(statusNotice.lastChild);
 | 
			
		||||
		}
 | 
			
		||||
		const lines = text.split('\n');
 | 
			
		||||
		lines.forEach((line) => {
 | 
			
		||||
			statusNotice.appendChild(document.createTextNode(line));
 | 
			
		||||
			statusNotice.appendChild(document.createElement('br'));
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function displayFailureNotice(err) {
 | 
			
		||||
		const msg = err.message || err;
 | 
			
		||||
		console.error(msg);
 | 
			
		||||
		setStatusNotice(msg);
 | 
			
		||||
		setStatusMode('notice');
 | 
			
		||||
		initializing = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const missing = Engine.getMissingFeatures();
 | 
			
		||||
	if (missing.length !== 0) {
 | 
			
		||||
		const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n';
 | 
			
		||||
		displayFailureNotice(missingMsg + missing.join('\n'));
 | 
			
		||||
	} else {
 | 
			
		||||
		setStatusMode('indeterminate');
 | 
			
		||||
		engine.startGame({
 | 
			
		||||
			'onProgress': function (current, total) {
 | 
			
		||||
				if (total > 0) {
 | 
			
		||||
					statusProgressInner.style.width = `${(current / total) * 100}%`;
 | 
			
		||||
					setStatusMode('progress');
 | 
			
		||||
					if (current === total) {
 | 
			
		||||
						// wait for progress bar animation
 | 
			
		||||
						setTimeout(() => {
 | 
			
		||||
							setStatusMode('indeterminate');
 | 
			
		||||
						}, 500);
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					setStatusMode('indeterminate');
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
		}).then(() => {
 | 
			
		||||
			setStatusMode('hidden');
 | 
			
		||||
			initializing = false;
 | 
			
		||||
		}, displayFailureNotice);
 | 
			
		||||
	}
 | 
			
		||||
}());
 | 
			
		||||
		</script>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								index.icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								index.icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 5.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								index.wasm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								index.wasm
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										161
									
								
								index.worker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								index.worker.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,161 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @license
 | 
			
		||||
 * Copyright 2015 The Emscripten Authors
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Pthread Web Worker startup routine:
 | 
			
		||||
// This is the entry point file that is loaded first by each Web Worker
 | 
			
		||||
// that executes pthreads on the Emscripten application.
 | 
			
		||||
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var Module = {};
 | 
			
		||||
 | 
			
		||||
// Thread-local guard variable for one-time init of the JS state
 | 
			
		||||
var initializedJS = false;
 | 
			
		||||
 | 
			
		||||
function assert(condition, text) {
 | 
			
		||||
  if (!condition) abort('Assertion failed: ' + text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function threadPrintErr() {
 | 
			
		||||
  var text = Array.prototype.slice.call(arguments).join(' ');
 | 
			
		||||
  console.error(text);
 | 
			
		||||
}
 | 
			
		||||
function threadAlert() {
 | 
			
		||||
  var text = Array.prototype.slice.call(arguments).join(' ');
 | 
			
		||||
  postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()});
 | 
			
		||||
}
 | 
			
		||||
// We don't need out() for now, but may need to add it if we want to use it
 | 
			
		||||
// here. Or, if this code all moves into the main JS, that problem will go
 | 
			
		||||
// away. (For now, adding it here increases code size for no benefit.)
 | 
			
		||||
var out = () => { throw 'out() is not defined in worker.js.'; }
 | 
			
		||||
var err = threadPrintErr;
 | 
			
		||||
self.alert = threadAlert;
 | 
			
		||||
 | 
			
		||||
Module['instantiateWasm'] = (info, receiveInstance) => {
 | 
			
		||||
  // Instantiate from the module posted from the main thread.
 | 
			
		||||
  // We can just use sync instantiation in the worker.
 | 
			
		||||
  var module = Module['wasmModule'];
 | 
			
		||||
  // We don't need the module anymore; new threads will be spawned from the main thread.
 | 
			
		||||
  Module['wasmModule'] = null;
 | 
			
		||||
  var instance = new WebAssembly.Instance(module, info);
 | 
			
		||||
  // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
 | 
			
		||||
  // the above line no longer optimizes out down to the following line.
 | 
			
		||||
  // When the regression is fixed, we can remove this if/else.
 | 
			
		||||
  return receiveInstance(instance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Turn unhandled rejected promises into errors so that the main thread will be
 | 
			
		||||
// notified about them.
 | 
			
		||||
self.onunhandledrejection = (e) => {
 | 
			
		||||
  throw e.reason ?? e;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function handleMessage(e) {
 | 
			
		||||
  try {
 | 
			
		||||
    if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.
 | 
			
		||||
 | 
			
		||||
    // Until we initialize the runtime, queue up any further incoming messages.
 | 
			
		||||
    let messageQueue = [];
 | 
			
		||||
    self.onmessage = (e) => messageQueue.push(e);
 | 
			
		||||
 | 
			
		||||
    // And add a callback for when the runtime is initialized.
 | 
			
		||||
    self.startWorker = (instance) => {
 | 
			
		||||
      Module = instance;
 | 
			
		||||
      // Notify the main thread that this thread has loaded.
 | 
			
		||||
      postMessage({ 'cmd': 'loaded' });
 | 
			
		||||
      // Process any messages that were queued before the thread was ready.
 | 
			
		||||
      for (let msg of messageQueue) {
 | 
			
		||||
        handleMessage(msg);
 | 
			
		||||
      }
 | 
			
		||||
      // Restore the real message handler.
 | 
			
		||||
      self.onmessage = handleMessage;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
      // Module and memory were sent from main thread
 | 
			
		||||
      Module['wasmModule'] = e.data.wasmModule;
 | 
			
		||||
 | 
			
		||||
      // Use `const` here to ensure that the variable is scoped only to
 | 
			
		||||
      // that iteration, allowing safe reference from a closure.
 | 
			
		||||
      for (const handler of e.data.handlers) {
 | 
			
		||||
        Module[handler] = function() {
 | 
			
		||||
          postMessage({ cmd: 'callHandler', handler, args: [...arguments] });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Module['wasmMemory'] = e.data.wasmMemory;
 | 
			
		||||
 | 
			
		||||
      Module['buffer'] = Module['wasmMemory'].buffer;
 | 
			
		||||
 | 
			
		||||
      Module['workerID'] = e.data.workerID;
 | 
			
		||||
 | 
			
		||||
      Module['ENVIRONMENT_IS_PTHREAD'] = true;
 | 
			
		||||
 | 
			
		||||
      if (typeof e.data.urlOrBlob == 'string') {
 | 
			
		||||
        importScripts(e.data.urlOrBlob);
 | 
			
		||||
      } else {
 | 
			
		||||
        var objectUrl = URL.createObjectURL(e.data.urlOrBlob);
 | 
			
		||||
        importScripts(objectUrl);
 | 
			
		||||
        URL.revokeObjectURL(objectUrl);
 | 
			
		||||
      }
 | 
			
		||||
      Godot(Module);
 | 
			
		||||
    } else if (e.data.cmd === 'run') {
 | 
			
		||||
      // Pass the thread address to wasm to store it for fast access.
 | 
			
		||||
      Module['__emscripten_thread_init'](e.data.pthread_ptr, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1);
 | 
			
		||||
 | 
			
		||||
      // Await mailbox notifications with `Atomics.waitAsync` so we can start
 | 
			
		||||
      // using the fast `Atomics.notify` notification path.
 | 
			
		||||
      Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr);
 | 
			
		||||
 | 
			
		||||
      assert(e.data.pthread_ptr);
 | 
			
		||||
      // Also call inside JS module to set up the stack frame for this pthread in JS module scope
 | 
			
		||||
      Module['establishStackSpace']();
 | 
			
		||||
      Module['PThread'].receiveObjectTransfer(e.data);
 | 
			
		||||
      Module['PThread'].threadInitTLS();
 | 
			
		||||
 | 
			
		||||
      if (!initializedJS) {
 | 
			
		||||
        initializedJS = true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      try {
 | 
			
		||||
        Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);
 | 
			
		||||
      } catch(ex) {
 | 
			
		||||
        if (ex != 'unwind') {
 | 
			
		||||
          // The pthread "crashed".  Do not call `_emscripten_thread_exit` (which
 | 
			
		||||
          // would make this thread joinable).  Instead, re-throw the exception
 | 
			
		||||
          // and let the top level handler propagate it back to the main thread.
 | 
			
		||||
          throw ex;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread.
 | 
			
		||||
      if (Module['_pthread_self']()) {
 | 
			
		||||
        Module['__emscripten_thread_exit'](-1);
 | 
			
		||||
      }
 | 
			
		||||
    } else if (e.data.target === 'setimmediate') {
 | 
			
		||||
      // no-op
 | 
			
		||||
    } else if (e.data.cmd === 'checkMailbox') {
 | 
			
		||||
      if (initializedJS) {
 | 
			
		||||
        Module['checkMailbox']();
 | 
			
		||||
      }
 | 
			
		||||
    } else if (e.data.cmd) {
 | 
			
		||||
      // The received message looks like something that should be handled by this message
 | 
			
		||||
      // handler, (since there is a e.data.cmd field present), but is not one of the
 | 
			
		||||
      // recognized commands:
 | 
			
		||||
      err('worker.js received unknown command ' + e.data.cmd);
 | 
			
		||||
      err(e.data);
 | 
			
		||||
    }
 | 
			
		||||
  } catch(ex) {
 | 
			
		||||
    err('worker.js onmessage() captured an uncaught exception: ' + ex);
 | 
			
		||||
    if (ex && ex.stack) err(ex.stack);
 | 
			
		||||
    if (Module['__emscripten_thread_crashed']) {
 | 
			
		||||
      Module['__emscripten_thread_crashed']();
 | 
			
		||||
    }
 | 
			
		||||
    throw ex;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
self.onmessage = handleMessage;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user