2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-06 15:15:42 +00:00
|
|
|
var CONST = require('./const');
|
2016-11-30 17:16:45 +00:00
|
|
|
var Set = require('../structs/Set');
|
|
|
|
var XHRSettings = require('./XHRSettings');
|
2016-12-06 15:15:42 +00:00
|
|
|
var Event = require('./events/');
|
2017-08-04 17:43:05 +00:00
|
|
|
// var EventDispatcher = require('../events/EventDispatcher');
|
2017-07-03 15:05:22 +00:00
|
|
|
var Class = require('../utils/Class');
|
2017-08-04 17:43:05 +00:00
|
|
|
var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont');
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
// Phaser.Loader.BaseLoader
|
2016-12-05 15:29:53 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
// To finish the loader ...
|
|
|
|
//
|
|
|
|
// 3) Progress update
|
2016-12-05 15:29:53 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
var BaseLoader = new Class({
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
initialize:
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-08-04 17:43:05 +00:00
|
|
|
function BaseLoader (scene)
|
2017-07-03 15:05:22 +00:00
|
|
|
{
|
2017-08-04 17:43:05 +00:00
|
|
|
this.scene = scene;
|
|
|
|
|
|
|
|
this.events = scene.sys.events;
|
2017-07-03 15:05:22 +00:00
|
|
|
|
|
|
|
// Move to a 'setURL' method?
|
|
|
|
this.baseURL = '';
|
|
|
|
this.path = '';
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
// Read from Game / Scene Config
|
2017-07-03 15:05:22 +00:00
|
|
|
this.enableParallel = true;
|
|
|
|
this.maxParallelDownloads = 4;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
// xhr specific global settings (can be overridden on a per-file basis)
|
|
|
|
this.xhr = XHRSettings();
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
this.crossOrigin = undefined;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
this.list = new Set();
|
|
|
|
this.inflight = new Set();
|
|
|
|
this.failed = new Set();
|
|
|
|
this.queue = new Set();
|
|
|
|
this.storage = new Set();
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_IDLE;
|
2017-07-03 15:05:22 +00:00
|
|
|
},
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-08-04 15:15:00 +00:00
|
|
|
setPath: function (path)
|
|
|
|
{
|
|
|
|
if (path.substr(-1) !== '/')
|
|
|
|
{
|
|
|
|
path = path.concat('/');
|
|
|
|
}
|
|
|
|
|
|
|
|
this.path = path;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
addFile: function (file)
|
|
|
|
{
|
|
|
|
if (!this.isReady())
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-12-12 22:27:53 +00:00
|
|
|
file.path = this.path;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-12 22:35:47 +00:00
|
|
|
this.list.set(file);
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
// Is the Loader actively loading (or processing loaded files)
|
|
|
|
isLoading: function ()
|
|
|
|
{
|
2017-07-14 13:30:20 +00:00
|
|
|
return (this.state === CONST.LOADER_LOADING || this.state === CONST.LOADER_PROCESSING);
|
2016-11-30 17:16:45 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Is the Loader ready to start a new load?
|
|
|
|
isReady: function ()
|
|
|
|
{
|
2017-07-14 13:30:20 +00:00
|
|
|
return (this.state === CONST.LOADER_IDLE || this.state === CONST.LOADER_COMPLETE || this.state === CONST.LOADER_FAILED);
|
2016-11-30 17:16:45 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
start: function ()
|
|
|
|
{
|
2017-07-14 13:30:20 +00:00
|
|
|
console.log(this.scene.sys.settings.key, '- BaseLoader start. Files to load:', this.list.size);
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
if (!this.isReady())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-06 15:15:42 +00:00
|
|
|
this.events.dispatch(new Event.LOADER_START_EVENT(this));
|
2016-12-05 17:19:12 +00:00
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
if (this.list.size === 0)
|
|
|
|
{
|
|
|
|
this.finishedLoading();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_LOADING;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
this.failed.clear();
|
|
|
|
this.inflight.clear();
|
|
|
|
this.queue.clear();
|
|
|
|
|
2016-12-08 16:21:16 +00:00
|
|
|
this.queue.debug = true;
|
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
this.updateProgress();
|
|
|
|
|
|
|
|
this.processLoadQueue();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
updateProgress: function ()
|
|
|
|
{
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
processLoadQueue: function ()
|
|
|
|
{
|
2016-12-08 16:21:16 +00:00
|
|
|
// console.log('======== BaseLoader processLoadQueue');
|
|
|
|
// console.log('List size', this.list.size);
|
|
|
|
// console.log(this.inflight.size, 'items still in flight. Can load another', (this.maxParallelDownloads - this.inflight.size));
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
var _this = this;
|
|
|
|
|
|
|
|
this.list.each(function (file)
|
|
|
|
{
|
2016-12-06 15:15:42 +00:00
|
|
|
if (file.state === CONST.FILE_PENDING && _this.inflight.size < _this.maxParallelDownloads)
|
2016-11-30 17:16:45 +00:00
|
|
|
{
|
2016-12-12 22:35:47 +00:00
|
|
|
_this.inflight.set(file);
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
_this.list.delete(file);
|
|
|
|
|
|
|
|
_this.loadFile(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_this.inflight.size === _this.maxParallelDownloads)
|
|
|
|
{
|
|
|
|
// Tells the Set iterator to abort
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// private
|
|
|
|
loadFile: function (file)
|
|
|
|
{
|
2016-12-06 15:25:24 +00:00
|
|
|
// console.log('LOADING', file.key);
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
// If the file doesn't have its own crossOrigin set,
|
|
|
|
// we'll use the Loaders (which is undefined by default)
|
|
|
|
if (!file.crossOrigin)
|
|
|
|
{
|
|
|
|
file.crossOrigin = this.crossOrigin;
|
|
|
|
}
|
|
|
|
|
2016-12-01 12:50:58 +00:00
|
|
|
file.load(this.nextFile.bind(this), this.baseURL);
|
2016-11-30 17:16:45 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
nextFile: function (previousFile, success)
|
|
|
|
{
|
2016-12-06 15:25:24 +00:00
|
|
|
// console.log('LOADED:', previousFile.src, success);
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
// Move the file that just loaded from the inflight list to the queue or failed Set
|
|
|
|
|
|
|
|
if (success)
|
|
|
|
{
|
2016-12-12 22:35:47 +00:00
|
|
|
this.queue.set(previousFile);
|
2016-11-30 17:16:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-12 22:35:47 +00:00
|
|
|
this.failed.set(previousFile);
|
2016-11-30 17:16:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.inflight.delete(previousFile);
|
|
|
|
|
|
|
|
if (this.list.size > 0)
|
|
|
|
{
|
2016-12-06 15:25:24 +00:00
|
|
|
// console.log('nextFile - still something in the list');
|
2016-11-30 17:16:45 +00:00
|
|
|
this.processLoadQueue();
|
|
|
|
}
|
|
|
|
else if (this.inflight.size === 0)
|
|
|
|
{
|
2016-12-06 15:25:24 +00:00
|
|
|
// console.log('nextFile calling finishedLoading');
|
2016-11-30 17:16:45 +00:00
|
|
|
this.finishedLoading();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
finishedLoading: function ()
|
|
|
|
{
|
2016-12-08 16:21:16 +00:00
|
|
|
// console.log('---> BaseLoader.finishedLoading PROCESSING', this.queue.size, 'files');
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_PROCESSING;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-08 16:21:16 +00:00
|
|
|
this.storage.clear();
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-07 00:27:56 +00:00
|
|
|
var _this = this;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
this.queue.each(function (file)
|
|
|
|
{
|
2016-12-08 16:21:16 +00:00
|
|
|
// console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;');
|
|
|
|
|
2016-12-07 00:27:56 +00:00
|
|
|
file.onProcess(_this.processUpdate.bind(_this));
|
|
|
|
});
|
|
|
|
},
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-07 04:43:02 +00:00
|
|
|
// Called automatically by the File when it has finished processing
|
2016-12-07 00:27:56 +00:00
|
|
|
processUpdate: function (file)
|
|
|
|
{
|
2016-12-08 16:21:16 +00:00
|
|
|
// console.log('-> processUpdate', file.key, file.state);
|
|
|
|
|
2016-12-07 04:43:02 +00:00
|
|
|
// This file has failed to load, so move it to the failed Set
|
2016-12-07 01:13:17 +00:00
|
|
|
if (file.state === CONST.FILE_ERRORED)
|
|
|
|
{
|
2016-12-12 22:35:47 +00:00
|
|
|
this.failed.set(file);
|
2016-12-07 04:43:02 +00:00
|
|
|
|
|
|
|
if (file.linkFile)
|
|
|
|
{
|
|
|
|
this.queue.delete(file.linkFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.removeFromQueue(file);
|
2016-12-07 01:13:17 +00:00
|
|
|
}
|
2016-12-07 04:43:02 +00:00
|
|
|
|
|
|
|
// If we got here, then the file loaded
|
|
|
|
|
|
|
|
// Special handling for multi-part files
|
|
|
|
|
|
|
|
if (file.linkFile)
|
2016-12-07 01:13:17 +00:00
|
|
|
{
|
2016-12-07 04:43:02 +00:00
|
|
|
if (file.state === CONST.FILE_COMPLETE && file.linkFile.state === CONST.FILE_COMPLETE)
|
|
|
|
{
|
|
|
|
// Partner has loaded, so add them both to Storage
|
2016-12-07 10:50:10 +00:00
|
|
|
|
2016-12-12 22:35:47 +00:00
|
|
|
this.storage.set({ type: file.linkType, fileA: file, fileB: file.linkFile });
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-07 04:43:02 +00:00
|
|
|
this.queue.delete(file.linkFile);
|
2016-12-07 01:13:17 +00:00
|
|
|
|
2016-12-07 04:43:02 +00:00
|
|
|
this.removeFromQueue(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2016-12-07 00:27:56 +00:00
|
|
|
{
|
2016-12-12 22:35:47 +00:00
|
|
|
this.storage.set(file);
|
2016-12-08 16:21:16 +00:00
|
|
|
|
2016-12-07 04:43:02 +00:00
|
|
|
this.removeFromQueue(file);
|
2016-12-07 00:27:56 +00:00
|
|
|
}
|
|
|
|
},
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-08 16:21:16 +00:00
|
|
|
removeFromQueue: function (file)
|
|
|
|
{
|
|
|
|
this.queue.delete(file);
|
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
if (this.queue.size === 0 && this.state === CONST.LOADER_PROCESSING)
|
2016-12-08 16:21:16 +00:00
|
|
|
{
|
|
|
|
// We've processed all the files we loaded
|
|
|
|
this.processComplete();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-12-07 00:27:56 +00:00
|
|
|
processComplete: function ()
|
|
|
|
{
|
2017-07-14 13:30:20 +00:00
|
|
|
console.log(this.scene.sys.settings.key, '- Loader Complete. Loaded:', this.storage.size, 'Failed:', this.failed.size);
|
2016-12-08 16:21:16 +00:00
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
this.list.clear();
|
|
|
|
this.inflight.clear();
|
|
|
|
this.queue.clear();
|
|
|
|
|
2017-08-04 17:43:05 +00:00
|
|
|
this.processCallback();
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_COMPLETE;
|
2016-11-30 17:16:45 +00:00
|
|
|
|
2016-12-06 15:15:42 +00:00
|
|
|
this.events.dispatch(new Event.LOADER_COMPLETE_EVENT(this));
|
2016-11-30 17:16:45 +00:00
|
|
|
},
|
|
|
|
|
2017-08-04 17:43:05 +00:00
|
|
|
// The Loader has finished
|
|
|
|
processCallback: function ()
|
|
|
|
{
|
|
|
|
if (this.storage.size === 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The global Texture Manager
|
|
|
|
var cache = this.scene.sys.cache;
|
|
|
|
var textures = this.scene.sys.textures;
|
|
|
|
var anims = this.scene.sys.anims;
|
|
|
|
|
|
|
|
// Process multiatlas groups first
|
|
|
|
|
|
|
|
var file;
|
|
|
|
var fileA;
|
|
|
|
var fileB;
|
|
|
|
|
|
|
|
for (var key in this._multilist)
|
|
|
|
{
|
|
|
|
var data = [];
|
|
|
|
var images = [];
|
|
|
|
var keys = this._multilist[key];
|
|
|
|
|
|
|
|
for (var i = 0; i < keys.length; i++)
|
|
|
|
{
|
|
|
|
file = this.storage.get('key', keys[i]);
|
|
|
|
|
|
|
|
if (file)
|
|
|
|
{
|
|
|
|
if (file.type === 'image')
|
|
|
|
{
|
|
|
|
images.push(file.data);
|
|
|
|
}
|
|
|
|
else if (file.type === 'json')
|
|
|
|
{
|
|
|
|
data.push(file.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.storage.delete(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do we have everything needed?
|
|
|
|
if (images.length + data.length === keys.length)
|
|
|
|
{
|
|
|
|
// Yup, add them to the Texture Manager
|
|
|
|
|
|
|
|
// Is the data JSON Hash or JSON Array?
|
|
|
|
if (Array.isArray(data[0].frames))
|
|
|
|
{
|
|
|
|
textures.addAtlasJSONArray(key, images, data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textures.addAtlasJSONHash(key, images, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process all of the files
|
|
|
|
|
|
|
|
// Because AnimationJSON may require images to be loaded first, we process them last
|
|
|
|
var animJSON = [];
|
|
|
|
|
|
|
|
this.storage.each(function (file)
|
|
|
|
{
|
|
|
|
switch (file.type)
|
|
|
|
{
|
|
|
|
case 'animationJSON':
|
|
|
|
animJSON.push(file);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'image':
|
|
|
|
case 'svg':
|
|
|
|
case 'html':
|
|
|
|
textures.addImage(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'atlasjson':
|
|
|
|
|
|
|
|
fileA = file.fileA;
|
|
|
|
fileB = file.fileB;
|
|
|
|
|
|
|
|
if (fileA.type === 'image')
|
|
|
|
{
|
|
|
|
textures.addAtlas(fileA.key, fileA.data, fileB.data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textures.addAtlas(fileB.key, fileB.data, fileA.data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-08-10 04:17:02 +00:00
|
|
|
case 'unityatlas':
|
|
|
|
|
|
|
|
fileA = file.fileA;
|
|
|
|
fileB = file.fileB;
|
|
|
|
|
|
|
|
if (fileA.type === 'image')
|
|
|
|
{
|
|
|
|
textures.addUnityAtlas(fileA.key, fileA.data, fileB.data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textures.addUnityAtlas(fileB.key, fileB.data, fileA.data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-08-04 17:43:05 +00:00
|
|
|
case 'bitmapfont':
|
|
|
|
|
|
|
|
fileA = file.fileA;
|
|
|
|
fileB = file.fileB;
|
|
|
|
|
|
|
|
if (fileA.type === 'image')
|
|
|
|
{
|
|
|
|
cache.bitmapFont.add(fileB.key, { data: ParseXMLBitmapFont(fileB.data), texture: fileA.key, frame: null });
|
|
|
|
textures.addImage(fileA.key, fileA.data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cache.bitmapFont.add(fileA.key, { data: ParseXMLBitmapFont(fileA.data), texture: fileB.key, frame: null });
|
|
|
|
textures.addImage(fileB.key, fileB.data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'spritesheet':
|
|
|
|
textures.addSpriteSheet(file.key, file.data, file.config);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'json':
|
|
|
|
cache.json.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'xml':
|
|
|
|
cache.xml.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'text':
|
|
|
|
cache.text.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'binary':
|
|
|
|
cache.binary.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'sound':
|
|
|
|
cache.sound.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'glsl':
|
|
|
|
cache.shader.add(file.key, file.data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
animJSON.forEach(function (file)
|
|
|
|
{
|
|
|
|
anims.fromJSON(file.data);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.storage.clear();
|
|
|
|
},
|
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
reset: function ()
|
|
|
|
{
|
|
|
|
this.list.clear();
|
|
|
|
this.inflight.clear();
|
|
|
|
this.failed.clear();
|
|
|
|
this.queue.clear();
|
|
|
|
this.storage.clear();
|
|
|
|
|
2017-02-07 12:54:20 +00:00
|
|
|
this.events.removeAll('LOADER_START_EVENT');
|
|
|
|
this.events.removeAll('LOADER_COMPLETE_EVENT');
|
|
|
|
|
2016-11-30 17:16:45 +00:00
|
|
|
this.tag = '';
|
|
|
|
this.path = '';
|
|
|
|
this.baseURL = '';
|
|
|
|
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_IDLE;
|
2016-11-30 17:16:45 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function ()
|
|
|
|
{
|
|
|
|
this.reset();
|
2017-07-14 13:30:20 +00:00
|
|
|
this.state = CONST.LOADER_DESTROYED;
|
2016-11-30 17:16:45 +00:00
|
|
|
}
|
|
|
|
|
2017-07-03 15:05:22 +00:00
|
|
|
});
|
2016-11-30 17:16:45 +00:00
|
|
|
|
|
|
|
module.exports = BaseLoader;
|