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);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |