mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-30 21:21:10 +00:00 
			
		
		
		
	 919bbf8077
			
		
	
	
		919bbf8077
		
	
	
	
	
		
			
			- Refactored the Engine code, splitted across files. - Use MODULARIZE option to build emscripten code into it's own closure. - Enable lto support (saves ~2MiB in release). - Enable optional closure compiler pass for JS and generated code. - Enable optional pthreads support. - Can now build with tools=yes (not much to see yet). - Dropped some deprecated code for older toolchains.
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var Preloader = /** @constructor */ function() {
 | |
| 
 | |
| 	var DOWNLOAD_ATTEMPTS_MAX = 4;
 | |
| 	var progressFunc = null;
 | |
| 	var lastProgress = { loaded: 0, total: 0 };
 | |
| 
 | |
| 	var loadingFiles = {};
 | |
| 	this.preloadedFiles = [];
 | |
| 
 | |
| 	function loadXHR(resolve, reject, file, tracker) {
 | |
| 		var xhr = new XMLHttpRequest;
 | |
| 		xhr.open('GET', file);
 | |
| 		if (!file.endsWith('.js')) {
 | |
| 			xhr.responseType = 'arraybuffer';
 | |
| 		}
 | |
| 		['loadstart', 'progress', 'load', 'error', 'abort'].forEach(function(ev) {
 | |
| 			xhr.addEventListener(ev, onXHREvent.bind(xhr, resolve, reject, file, tracker));
 | |
| 		});
 | |
| 		xhr.send();
 | |
| 	}
 | |
| 
 | |
| 	function onXHREvent(resolve, reject, file, tracker, ev) {
 | |
| 
 | |
| 		if (this.status >= 400) {
 | |
| 
 | |
| 			if (this.status < 500 || ++tracker[file].attempts >= DOWNLOAD_ATTEMPTS_MAX) {
 | |
| 				reject(new Error("Failed loading file '" + file + "': " + this.statusText));
 | |
| 				this.abort();
 | |
| 				return;
 | |
| 			} else {
 | |
| 				setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		switch (ev.type) {
 | |
| 			case 'loadstart':
 | |
| 				if (tracker[file] === undefined) {
 | |
| 					tracker[file] = {
 | |
| 						total: ev.total,
 | |
| 						loaded: ev.loaded,
 | |
| 						attempts: 0,
 | |
| 						final: false,
 | |
| 					};
 | |
| 				}
 | |
| 				break;
 | |
| 
 | |
| 			case 'progress':
 | |
| 				tracker[file].loaded = ev.loaded;
 | |
| 				tracker[file].total = ev.total;
 | |
| 				break;
 | |
| 
 | |
| 			case 'load':
 | |
| 				tracker[file].final = true;
 | |
| 				resolve(this);
 | |
| 				break;
 | |
| 
 | |
| 			case 'error':
 | |
| 				if (++tracker[file].attempts >= DOWNLOAD_ATTEMPTS_MAX) {
 | |
| 					tracker[file].final = true;
 | |
| 					reject(new Error("Failed loading file '" + file + "'"));
 | |
| 				} else {
 | |
| 					setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000);
 | |
| 				}
 | |
| 				break;
 | |
| 
 | |
| 			case 'abort':
 | |
| 				tracker[file].final = true;
 | |
| 				reject(new Error("Loading file '" + file + "' was aborted."));
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	this.loadPromise = function(file) {
 | |
| 		return new Promise(function(resolve, reject) {
 | |
| 			loadXHR(resolve, reject, file, loadingFiles);
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	this.preload = function(pathOrBuffer, destPath) {
 | |
| 		if (pathOrBuffer instanceof ArrayBuffer) {
 | |
| 			pathOrBuffer = new Uint8Array(pathOrBuffer);
 | |
| 		} else if (ArrayBuffer.isView(pathOrBuffer)) {
 | |
| 			pathOrBuffer = new Uint8Array(pathOrBuffer.buffer);
 | |
| 		}
 | |
| 		if (pathOrBuffer instanceof Uint8Array) {
 | |
| 			this.preloadedFiles.push({
 | |
| 				path: destPath,
 | |
| 				buffer: pathOrBuffer
 | |
| 			});
 | |
| 			return Promise.resolve();
 | |
| 		} else if (typeof pathOrBuffer === 'string') {
 | |
| 			var me = this;
 | |
| 			return this.loadPromise(pathOrBuffer).then(function(xhr) {
 | |
| 				me.preloadedFiles.push({
 | |
| 					path: destPath || pathOrBuffer,
 | |
| 					buffer: xhr.response
 | |
| 				});
 | |
| 				return Promise.resolve();
 | |
| 			});
 | |
| 		} else {
 | |
| 			throw Promise.reject("Invalid object for preloading");
 | |
| 		}
 | |
| 	};
 | |
| 
 | |
| 	var animateProgress = function() {
 | |
| 
 | |
| 		var loaded = 0;
 | |
| 		var total = 0;
 | |
| 		var totalIsValid = true;
 | |
| 		var progressIsFinal = true;
 | |
| 
 | |
| 		Object.keys(loadingFiles).forEach(function(file) {
 | |
| 			const stat = loadingFiles[file];
 | |
| 			if (!stat.final) {
 | |
| 				progressIsFinal = false;
 | |
| 			}
 | |
| 			if (!totalIsValid || stat.total === 0) {
 | |
| 				totalIsValid = false;
 | |
| 				total = 0;
 | |
| 			} else {
 | |
| 				total += stat.total;
 | |
| 			}
 | |
| 			loaded += stat.loaded;
 | |
| 		});
 | |
| 		if (loaded !== lastProgress.loaded || total !== lastProgress.total) {
 | |
| 			lastProgress.loaded = loaded;
 | |
| 			lastProgress.total = total;
 | |
| 			if (typeof progressFunc === 'function')
 | |
| 				progressFunc(loaded, total);
 | |
| 		}
 | |
| 		if (!progressIsFinal)
 | |
| 			requestAnimationFrame(animateProgress);
 | |
| 	}
 | |
| 	this.animateProgress = animateProgress; // Also exposed to start it.
 | |
| 
 | |
| 	this.setProgressFunc = function(callback) {
 | |
| 		progressFunc = callback;
 | |
| 	}
 | |
| };
 |