Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta Zip Loading #180

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/flambe/asset/AssetEntry.hx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ enum AssetFormat

// Raw text/data
Data;

// Archived file format
ZIP; TAR;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/flambe/asset/Manifest.hx
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class Manifest
return basePath;
}

private static function inferFormat (url :String) :AssetFormat
public static function inferFormat (url :String) :AssetFormat
{
var extension = url.getUrlExtension();
if (extension != null) {
Expand All @@ -216,6 +216,8 @@ class Manifest
case "ogg": return OGG;
case "opus": return OPUS;
case "wav": return WAV;
case "zip": return ZIP;
case "tar": return TAR;
}
} else {
Log.warn("No file extension for asset, it will be loaded as data", ["url", url]);
Expand Down
2 changes: 1 addition & 1 deletion src/flambe/platform/BasicAssetPackLoader.hx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class BasicAssetPackLoader
map = _pack.textures;
case MP3, M4A, OPUS, OGG, WAV:
map = _pack.sounds;
case Data:
case Data, ZIP, TAR:
map = _pack.files;
}

Expand Down
150 changes: 149 additions & 1 deletion src/flambe/platform/flash/FlashAssetPackLoader.hx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ import flambe.asset.AssetEntry;
import flambe.asset.Manifest;
import flambe.util.Assert;

import format.tar.Data;

import haxe.io.BytesInput;
import haxe.io.Bytes;

using flambe.util.Strings;
using StringTools;

class FlashAssetPackLoader extends BasicAssetPackLoader
{
public function new (platform :FlashPlatform, manifest :Manifest)
Expand Down Expand Up @@ -66,6 +74,146 @@ class FlashAssetPackLoader extends BasicAssetPackLoader
var urlLoader = new URLLoader(req);
dispatcher = urlLoader;
create = function () return new BasicFile(urlLoader.data);

case ZIP:
var urlLoader = new URLLoader(req);
urlLoader.dataFormat = flash.net.URLLoaderDataFormat.BINARY;
dispatcher = urlLoader;
var events = new EventGroup();
events.addDisposingListener(dispatcher, Event.COMPLETE, function (_) {
var bytes = Bytes.ofData(urlLoader.data);
var zip = new haxe.zip.Reader(new BytesInput(bytes));
var entries:List<haxe.zip.Entry> = zip.read();

for (entry in entries) {
var extension = entry.fileName.getUrlExtension();
if(entry.fileName.charAt(0)=="." || entry.fileName.indexOf("/.")>=0) {
extension="";
}
if(extension=="" || extension==null) {
Log.warn("No extension or weird format for zipped entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

_assetsRemaining += 1;
promise.total += entry.dataSize;

var format = Manifest.inferFormat(entry.fileName);
var name = entry.fileName.removeFileExtension();
if(format == Data) {
name = entry.fileName;
}
var entryFlambe = manifest.add(name, entry.fileName, entry.dataSize, format);
var asset;
var canAdd = false;
switch(format) {
case JXR, PNG, JPG, GIF:
var loader = new Loader();
loader.loadBytes(entry.data.getData());
var dispatcher:IEventDispatcher = loader.contentLoaderInfo;
var events = new EventGroup();
events.addDisposingListener(dispatcher, Event.COMPLETE, function (_) {
create = function () {
var bitmap :Bitmap = cast loader.content;
var texture = _platform.getRenderer().createTexture(bitmap.bitmapData);
bitmap.bitmapData.dispose();
return texture;
};
asset = create();
handleLoad(entryFlambe, asset);
});
case MP3:
var sound = new Sound();
sound.loadCompressedDataFromByteArray(entry.data.getData(), entry.dataSize);
create = function () return new FlashSound(sound);
canAdd = true;
case Data:
create = function () return new BasicFile(entry.data.toString());
canAdd = true;
default:
Log.warn("Format not supported for zipped entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

if (canAdd) {
asset = create();
handleLoad(entryFlambe, asset);
}
}
});
handleLoad(entry, {});
return;

case TAR:
var urlLoader = new URLLoader(req);
urlLoader.dataFormat = flash.net.URLLoaderDataFormat.BINARY;
dispatcher = urlLoader;
var events = new EventGroup();
events.addDisposingListener(dispatcher, Event.COMPLETE, function (_) {
var bytes = Bytes.ofData(urlLoader.data);
var tar = new format.tar.Reader(new BytesInput(bytes));
var entries:List<format.tar.Entry> = tar.read();

for (entry in entries) {
var extension = entry.fileName.getUrlExtension();
if(entry.fileName.charAt(0)=="." || entry.fileName.indexOf("/.")>=0) {
extension="";
}
if(extension=="" || extension==null) {
Log.warn("No extension or weird format for tar entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

_assetsRemaining += 1;
promise.total += entry.fileSize;

var format = Manifest.inferFormat(entry.fileName);
var name = entry.fileName.removeFileExtension();
if(format == Data) {
name = entry.fileName;
}
var entryFlambe = manifest.add(name, entry.fileName, entry.fileSize, format);
var asset;
var canAdd = false;
switch(format) {
case JXR, PNG, JPG, GIF:
var loader = new Loader();
loader.loadBytes(entry.data.getData());
var dispatcher:IEventDispatcher = loader.contentLoaderInfo;
var events = new EventGroup();
events.addDisposingListener(dispatcher, Event.COMPLETE, function (_) {
create = function () {
var bitmap :Bitmap = cast loader.content;
var texture = _platform.getRenderer().createTexture(bitmap.bitmapData);
bitmap.bitmapData.dispose();
return texture;
};
asset = create();
handleLoad(entryFlambe, asset);
});
case MP3:
var sound = new Sound();
sound.loadCompressedDataFromByteArray(entry.data.getData(), entry.fileSize);
create = function () return new FlashSound(sound);
canAdd = true;
case Data:
create = function () return new BasicFile(entry.data.toString());
canAdd = true;
default:
_assetsRemaining -= 1;
promise.total -= entry.fileSize;
Log.warn("Format not supported for tar entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

if (canAdd) {
asset = create();
handleLoad(entryFlambe, asset);
}
}
});
handleLoad(entry, {});
return;

default:
// Should never happen
Expand Down Expand Up @@ -102,6 +250,6 @@ class FlashAssetPackLoader extends BasicAssetPackLoader

override private function getAssetFormats (fn :Array<AssetFormat> -> Void)
{
fn([JXR, PNG, JPG, GIF, MP3, Data]);
fn([JXR, PNG, JPG, GIF, MP3, Data, ZIP, TAR]);
}
}
129 changes: 127 additions & 2 deletions src/flambe/platform/html/HtmlAssetPackLoader.hx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import js.Browser;
import js.html.*;

import haxe.Http;
import haxe.io.BytesInput;
import haxe.io.Bytes;

import flambe.asset.AssetEntry;
import flambe.asset.Manifest;
Expand All @@ -16,6 +18,11 @@ import flambe.util.Promise;
import flambe.util.Signal0;
import flambe.util.Signal1;

import format.tar.Data;

using StringTools;
using flambe.util.Strings;

class HtmlAssetPackLoader extends BasicAssetPackLoader
{
public function new (platform :HtmlPlatform, manifest :Manifest)
Expand Down Expand Up @@ -138,16 +145,127 @@ class HtmlAssetPackLoader extends BasicAssetPackLoader
downloadText(url, entry, function (text) {
handleLoad(entry, new BasicFile(text));
});

case ZIP:
if (supportsBlob()) {
downloadArrayBuffer(url, entry, function (buffer) {
var bytes = Bytes.ofData(cast new js.html.Uint8Array(buffer));
var zip = new haxe.zip.Reader(new BytesInput(bytes));
var entries:List<haxe.zip.Entry> = zip.read();

for (entry in entries) {
var extension = entry.fileName.getUrlExtension();
if(entry.fileName.charAt(0)=="." || entry.fileName.indexOf("/.")>=0) {
extension="";
}
if(extension=="" || extension==null) {
Log.warn("No extension or weird format for zipped entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

_assetsRemaining += 1;
promise.total += entry.dataSize;

var type = "";
var format = Manifest.inferFormat(entry.fileName);
var name = entry.fileName.removeFileExtension();
switch(format) {
case PNG: type = "image/png";
case JPG: type = "image/jpeg";
case JXR: type = "image/vnd.ms-photo";
case GIF: type = "image/gif";
case WEBP: type = "image/webp";
case M4A: type = "audio/mp4";
case MP3: type = "audio/mpeg";
case OGG, OPUS: type = "audio/ogg";
case WAV: type = "audio/wave";
case Data: name = entry.fileName;
case ZIP: type = "application/zip";
case DDS, PVR, PKM: type = "application/octet-stream";
case TAR: type = "application/x-tar";
}

var buff = new js.html.Uint8Array(entry.data.getData());
var blob = new Blob([buff], {type:type});
if(format == Data) {
blob = new Blob([haxe.zip.Reader.unzip(entry)], {type:type});
}
var generatedUrl = _URL.createObjectURL(blob);
var entryFlambe = manifest.add(name, entry.fileName, entry.dataSize, format);
loadEntry(generatedUrl, entryFlambe);
}
});
} else {
Log.warn("Blob not supported, ignoring this asset", ["url", url]);
}
handleLoad(entry, {});
case TAR:
if (supportsBlob()) {
downloadArrayBuffer(url, entry, function (buffer) {
var bytes = Bytes.ofData(cast new js.html.Uint8Array(buffer));
var tar = new format.tar.Reader(new BytesInput(bytes));
var entries:List<format.tar.Entry> = tar.read();

for (entry in entries) {
var extension = entry.fileName.getUrlExtension();
if(entry.fileName.charAt(0)=="." || entry.fileName.indexOf("/.")>=0) {
extension="";
}
if(extension=="" || extension==null) {
Log.warn("No extension or weird format for tar entry, ignoring this asset", ["url", entry.fileName]);
continue;
}

_assetsRemaining += 1;
promise.total += entry.fileSize;

loadTarEntry(entry);
};
});
} else {
Log.warn("Blob not supported, ignoring this asset", ["url", url]);
}
handleLoad(entry, {});
}
}


private function loadTarEntry (entry:format.tar.Entry) {
var type = "";
var format = Manifest.inferFormat(entry.fileName);
var name = entry.fileName.removeFileExtension();
switch(format) {
case PNG: type = "image/png";
case JPG: type = "image/jpeg";
case JXR: type = "image/vnd.ms-photo";
case GIF: type = "image/gif";
case WEBP: type = "image/webp";
case M4A: type = "audio/mp4";
case MP3: type = "audio/mpeg";
case OGG, OPUS: type = "audio/ogg";
case WAV: type = "audio/wave";
case Data: name = entry.fileName;
case ZIP: type = "application/zip";
case DDS, PVR, PKM: type = "application/octet-stream";
case TAR: type = "application/x-tar";
}
var buff = new js.html.Uint8Array(entry.data.getData());
var blob = new Blob([buff], {type:type});
if(format == Data) {
blob = new Blob([entry.data], {type:type});
}
var generatedUrl = _URL.createObjectURL(blob);
var entryFlambe = manifest.add(name, entry.fileName, entry.fileSize, format);
loadEntry(generatedUrl, entryFlambe);
}

override private function getAssetFormats (fn :Array<AssetFormat> -> Void)
{
if (_supportedFormats == null) {
_supportedFormats = new Promise();
detectImageFormats(function (imageFormats) {
_supportedFormats.result = _platform.getRenderer().getCompressedTextureFormats()
.concat(imageFormats).concat(detectAudioFormats()).concat([Data]);
.concat(imageFormats).concat(detectAudioFormats()).concat(detectArchiveFormats())
.concat([Data]);
});
}
_supportedFormats.get(fn);
Expand Down Expand Up @@ -313,6 +431,13 @@ class HtmlAssetPackLoader extends BasicAssetPackLoader
return result;
}

private static function detectArchiveFormats () :Array<AssetFormat>
{
var result = [ZIP, TAR];

return result;
}

private static function supportsBlob () :Bool
{
if (_detectBlobSupport) {
Expand Down