237 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			237 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | package kha; | ||
|  | 
 | ||
|  | import js.html.FileReader; | ||
|  | import js.Syntax; | ||
|  | import js.Browser; | ||
|  | import js.html.ImageElement; | ||
|  | import js.html.XMLHttpRequest; | ||
|  | import haxe.io.Bytes; | ||
|  | import kha.Blob; | ||
|  | import kha.js.WebAudioSound; | ||
|  | import kha.js.MobileWebAudioSound; | ||
|  | import kha.graphics4.TextureFormat; | ||
|  | import kha.graphics4.Usage; | ||
|  | 
 | ||
|  | using StringTools; | ||
|  | 
 | ||
|  | class LoaderImpl { | ||
|  | 	@:allow(kha.SystemImpl) | ||
|  | 	static var dropFiles = new Map<String, js.html.File>(); | ||
|  | 
 | ||
|  | 	public static function getImageFormats(): Array<String> { | ||
|  | 		return ["png", "jpg", "hdr"]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadImageFromDescription(desc: Dynamic, done: kha.Image->Void, failed: AssetError->Void) { | ||
|  | 		var readable = Reflect.hasField(desc, "readable") ? desc.readable : false; | ||
|  | 		if (StringTools.endsWith(desc.files[0], ".hdr")) { | ||
|  | 			loadBlobFromDescription(desc, function(blob) { | ||
|  | 				var hdrImage = kha.internal.HdrFormat.parse(blob.toBytes()); | ||
|  | 				done(Image.fromBytes(hdrImage.data.view.buffer, hdrImage.width, hdrImage.height, TextureFormat.RGBA128, | ||
|  | 					readable ? Usage.DynamicUsage : Usage.StaticUsage)); | ||
|  | 			}, failed); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			var img: ImageElement = cast Browser.document.createElement("img"); | ||
|  | 			img.onerror = function(event: Dynamic) failed({url: desc.files[0], error: event}); | ||
|  | 			img.onload = function(event: Dynamic) done(Image.fromImage(img, readable)); | ||
|  | 			img.crossOrigin = ""; | ||
|  | 			img.src = desc.files[0]; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getSoundFormats(): Array<String> { | ||
|  | 		var element = Browser.document.createAudioElement(); | ||
|  | 		var formats = new Array<String>(); | ||
|  | 		#if !kha_debug_html5 | ||
|  | 		if (element.canPlayType("audio/mp4") != "") | ||
|  | 			formats.push("mp4"); | ||
|  | 		if (element.canPlayType("audio/mp3") != "") | ||
|  | 			formats.push("mp3"); | ||
|  | 		if (element.canPlayType("audio/wav") != "") | ||
|  | 			formats.push("wav"); | ||
|  | 		#end | ||
|  | 		if (SystemImpl._hasWebAudio || element.canPlayType("audio/ogg") != "") | ||
|  | 			formats.push("ogg"); | ||
|  | 		return formats; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) { | ||
|  | 		if (SystemImpl._hasWebAudio) { | ||
|  | 			#if !kha_debug_html5 | ||
|  | 			var element = Browser.document.createAudioElement(); | ||
|  | 			if (element.canPlayType("audio/mp4") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".mp4")) { | ||
|  | 						new WebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			if (element.canPlayType("audio/mp3") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".mp3")) { | ||
|  | 						new WebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			if (element.canPlayType("audio/wav") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".wav")) { | ||
|  | 						new WebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			#end | ||
|  | 			for (i in 0...desc.files.length) { | ||
|  | 				var file: String = desc.files[i]; | ||
|  | 				if (file.endsWith(".ogg")) { | ||
|  | 					new WebAudioSound(file, done, failed); | ||
|  | 					return; | ||
|  | 				} | ||
|  | 			} | ||
|  | 			failed({ | ||
|  | 				url: desc.files.join(","), | ||
|  | 				error: "Unable to find sound files with supported audio formats", | ||
|  | 			}); | ||
|  | 		} | ||
|  | 		else if (SystemImpl.mobile) { | ||
|  | 			var element = Browser.document.createAudioElement(); | ||
|  | 			if (element.canPlayType("audio/mp4") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".mp4")) { | ||
|  | 						new MobileWebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			if (element.canPlayType("audio/mp3") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".mp3")) { | ||
|  | 						new MobileWebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			if (element.canPlayType("audio/wav") != "") { | ||
|  | 				for (i in 0...desc.files.length) { | ||
|  | 					var file: String = desc.files[i]; | ||
|  | 					if (file.endsWith(".wav")) { | ||
|  | 						new MobileWebAudioSound(file, done, failed); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			for (i in 0...desc.files.length) { | ||
|  | 				var file: String = desc.files[i]; | ||
|  | 				if (file.endsWith(".ogg")) { | ||
|  | 					new MobileWebAudioSound(file, done, failed); | ||
|  | 					return; | ||
|  | 				} | ||
|  | 			} | ||
|  | 			failed({ | ||
|  | 				url: desc.files.join(","), | ||
|  | 				error: "Unable to find sound files with supported audio formats", | ||
|  | 			}); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			new kha.js.Sound(desc.files, done, failed); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getVideoFormats(): Array<String> { | ||
|  | 		#if kha_debug_html5 | ||
|  | 		return ["webm"]; | ||
|  | 		#else | ||
|  | 		return ["mp4", "webm"]; | ||
|  | 		#end | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadVideoFromDescription(desc: Dynamic, done: kha.Video->Void, failed: AssetError->Void): Void { | ||
|  | 		kha.js.Video.fromFile(desc.files, done); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadRemote(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) { | ||
|  | 		var request = untyped new XMLHttpRequest(); | ||
|  | 		request.open("GET", desc.files[0], true); | ||
|  | 		request.responseType = "arraybuffer"; | ||
|  | 
 | ||
|  | 		request.onreadystatechange = function() { | ||
|  | 			if (request.readyState != 4) | ||
|  | 				return; | ||
|  | 			if ((request.status >= 200 && request.status < 400) | ||
|  | 				|| (request.status == 0 && request.statusText == "")) { // Blobs loaded using --allow-file-access-from-files | ||
|  | 				var bytes: Bytes = null; | ||
|  | 				var arrayBuffer = request.response; | ||
|  | 				if (arrayBuffer != null) { | ||
|  | 					var byteArray: Dynamic = Syntax.code("new Uint8Array(arrayBuffer)"); | ||
|  | 					bytes = Bytes.ofData(byteArray); | ||
|  | 				} | ||
|  | 				else if (request.responseBody != null) { | ||
|  | 					var data: Dynamic = untyped Syntax.code("VBArray(request.responseBody).toArray()"); | ||
|  | 					bytes = Bytes.alloc(data.length); | ||
|  | 					for (i in 0...data.length) | ||
|  | 						bytes.set(i, data[i]); | ||
|  | 				} | ||
|  | 				else { | ||
|  | 					failed({url: desc.files[0]}); | ||
|  | 					return; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				done(new Blob(bytes)); | ||
|  | 			} | ||
|  | 			else { | ||
|  | 				failed({url: desc.files[0]}); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		request.send(null); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadBlobFromDescription(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) { | ||
|  | 		#if kha_debug_html5 | ||
|  | 		var file: String = desc.files[0]; | ||
|  | 
 | ||
|  | 		if (file.startsWith("http://") || file.startsWith("https://")) { | ||
|  | 			loadRemote(desc, done, failed); | ||
|  | 		} | ||
|  | 		else if (file.startsWith("drop://")) { | ||
|  | 			var dropFile = dropFiles.get(file.substring(7)); | ||
|  | 			if (dropFile == null) | ||
|  | 				failed({url: file, error: 'file not found'}); | ||
|  | 			else { | ||
|  | 				var reader = new FileReader(); | ||
|  | 				reader.onloadend = () -> { | ||
|  | 					done(new Blob(Bytes.ofData(reader.result))); | ||
|  | 				}; | ||
|  | 				reader.onerror = () -> failed({url: file, error: reader.error}); | ||
|  | 				reader.readAsArrayBuffer(dropFile); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			var loadBlob = Syntax.code("window.electron.loadBlob"); | ||
|  | 			loadBlob(desc, (byteArray: Dynamic) -> { | ||
|  | 				var bytes = Bytes.alloc(byteArray.byteLength); | ||
|  | 				for (i in 0...byteArray.byteLength) | ||
|  | 					bytes.set(i, byteArray[i]); | ||
|  | 				done(new Blob(bytes)); | ||
|  | 			}, failed); | ||
|  | 		} | ||
|  | 		#else | ||
|  | 		loadRemote(desc, done, failed); | ||
|  | 		#end | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function loadFontFromDescription(desc: Dynamic, done: Font->Void, failed: AssetError->Void): Void { | ||
|  | 		loadBlobFromDescription(desc, function(blob: Blob) { | ||
|  | 			done(new Font(blob)); | ||
|  | 		}, failed); | ||
|  | 	} | ||
|  | } |