2017-10-11 16:05:59 +00:00
|
|
|
var CanvasPool = require('../display/canvas/CanvasPool');
|
2017-07-04 12:23:58 +00:00
|
|
|
var Class = require('../utils/Class');
|
2017-10-11 16:05:59 +00:00
|
|
|
var Color = require('../display/color/Color');
|
2018-01-18 14:01:29 +00:00
|
|
|
var EventEmitter = require('eventemitter3');
|
2017-06-15 00:34:05 +00:00
|
|
|
var GenerateTexture = require('../create/GenerateTexture');
|
2017-07-04 12:23:58 +00:00
|
|
|
var GetValue = require('../utils/object/GetValue');
|
|
|
|
var Parser = require('./parsers');
|
|
|
|
var Texture = require('./Texture');
|
2016-12-06 16:18:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Textures are managed by the global TextureManager. This is a singleton class that is
|
|
|
|
* responsible for creating and delivering Textures and their corresponding Frames to Game Objects.
|
|
|
|
*
|
|
|
|
* Sprites and other Game Objects get the texture data they need from the TextureManager.
|
|
|
|
*
|
2017-07-14 13:30:20 +00:00
|
|
|
* Access it via `scene.textures`.
|
2016-12-06 16:18:28 +00:00
|
|
|
*/
|
2017-07-04 12:23:58 +00:00
|
|
|
var TextureManager = new Class({
|
2017-01-19 23:20:36 +00:00
|
|
|
|
2018-01-18 14:01:29 +00:00
|
|
|
Extends: EventEmitter,
|
|
|
|
|
2017-07-04 12:23:58 +00:00
|
|
|
initialize:
|
2017-02-07 12:43:20 +00:00
|
|
|
|
2017-07-04 12:23:58 +00:00
|
|
|
function TextureManager (game)
|
|
|
|
{
|
2018-01-18 14:01:29 +00:00
|
|
|
EventEmitter.call(this);
|
|
|
|
|
2017-07-04 12:23:58 +00:00
|
|
|
this.game = game;
|
2016-12-06 16:18:28 +00:00
|
|
|
|
2018-01-18 05:16:52 +00:00
|
|
|
this.name = 'TextureManager';
|
|
|
|
|
2017-07-04 12:23:58 +00:00
|
|
|
this.list = {};
|
2016-12-06 16:18:28 +00:00
|
|
|
|
2017-07-16 11:44:45 +00:00
|
|
|
this._tempCanvas = CanvasPool.create2D(this, 1, 1);
|
|
|
|
this._tempContext = this._tempCanvas.getContext('2d');
|
2018-01-18 05:16:52 +00:00
|
|
|
|
2018-01-18 14:01:29 +00:00
|
|
|
this._pending = 0;
|
|
|
|
|
2018-01-18 05:16:52 +00:00
|
|
|
game.events.once('boot', this.boot, this);
|
2017-09-16 20:07:42 +00:00
|
|
|
},
|
2017-07-16 11:44:45 +00:00
|
|
|
|
2017-09-16 20:07:42 +00:00
|
|
|
boot: function ()
|
|
|
|
{
|
2018-01-18 14:01:29 +00:00
|
|
|
this._pending = 2;
|
|
|
|
|
|
|
|
this.on('onload', this.updatePending, this);
|
|
|
|
this.on('onerror', this.updatePending, this);
|
|
|
|
|
2017-09-16 20:07:42 +00:00
|
|
|
this.addBase64('__DEFAULT', this.game.config.defaultImage);
|
|
|
|
this.addBase64('__MISSING', this.game.config.missingImage);
|
2017-07-04 12:23:58 +00:00
|
|
|
},
|
2016-12-06 16:18:28 +00:00
|
|
|
|
2018-01-18 14:01:29 +00:00
|
|
|
updatePending: function ()
|
|
|
|
{
|
|
|
|
this._pending--;
|
|
|
|
|
|
|
|
if (this._pending === 0)
|
|
|
|
{
|
|
|
|
this.off('onload');
|
|
|
|
this.off('onerror');
|
|
|
|
|
|
|
|
this.game.events.emit('ready');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-02-07 12:43:20 +00:00
|
|
|
addBase64: function (key, data)
|
|
|
|
{
|
|
|
|
var _this = this;
|
2018-01-18 14:01:29 +00:00
|
|
|
|
2017-02-07 12:43:20 +00:00
|
|
|
var image = new Image();
|
|
|
|
|
2018-01-18 14:01:29 +00:00
|
|
|
image.onerror = function ()
|
|
|
|
{
|
|
|
|
_this.emit('onerror', key);
|
|
|
|
};
|
|
|
|
|
2017-02-07 12:43:20 +00:00
|
|
|
image.onload = function ()
|
|
|
|
{
|
|
|
|
var texture = _this.create(key, image);
|
|
|
|
|
|
|
|
Parser.Image(texture, 0);
|
2018-01-18 14:01:29 +00:00
|
|
|
|
|
|
|
_this.emit('onload', key, texture);
|
2017-02-07 12:43:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
image.src = data;
|
|
|
|
},
|
|
|
|
|
2018-01-29 23:38:27 +00:00
|
|
|
addImage: function (key, source, dataSource)
|
2016-12-06 16:18:28 +00:00
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
Parser.Image(texture, 0);
|
|
|
|
|
2018-01-29 23:38:27 +00:00
|
|
|
if (dataSource)
|
|
|
|
{
|
|
|
|
texture.setDataSource(dataSource);
|
|
|
|
}
|
|
|
|
|
2016-12-06 16:18:28 +00:00
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-06-15 00:34:05 +00:00
|
|
|
generate: function (key, config)
|
|
|
|
{
|
|
|
|
var canvas = CanvasPool.create(this, 1, 1);
|
|
|
|
|
|
|
|
config.canvas = canvas;
|
|
|
|
|
|
|
|
GenerateTexture(config);
|
|
|
|
|
|
|
|
return this.addCanvas(key, canvas);
|
|
|
|
},
|
|
|
|
|
2017-03-14 16:37:32 +00:00
|
|
|
createCanvas: function (key, width, height)
|
|
|
|
{
|
|
|
|
if (width === undefined) { width = 256; }
|
|
|
|
if (height === undefined) { height = 256; }
|
|
|
|
|
|
|
|
var canvas = CanvasPool.create(this, width, height);
|
|
|
|
|
|
|
|
return this.addCanvas(key, canvas);
|
|
|
|
},
|
|
|
|
|
2016-12-06 16:18:28 +00:00
|
|
|
addCanvas: function (key, source)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
Parser.Canvas(texture, 0);
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2016-12-07 10:50:10 +00:00
|
|
|
addAtlas: function (key, source, data)
|
|
|
|
{
|
|
|
|
// Is it a Hash or an Array?
|
|
|
|
|
|
|
|
if (Array.isArray(data.frames))
|
|
|
|
{
|
|
|
|
return this.addAtlasJSONArray(key, source, data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this.addAtlasJSONHash(key, source, data);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-12-06 16:18:28 +00:00
|
|
|
addAtlasJSONArray: function (key, source, data)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
if (Array.isArray(data))
|
|
|
|
{
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
{
|
|
|
|
Parser.JSONArray(texture, i, data[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Parser.JSONArray(texture, 0, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
|
|
|
addAtlasJSONHash: function (key, source, data)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
if (Array.isArray(data))
|
|
|
|
{
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
{
|
|
|
|
Parser.JSONHash(texture, i, data[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Parser.JSONHash(texture, 0, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-08-10 04:17:02 +00:00
|
|
|
addUnityAtlas: function (key, source, data)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
Parser.UnityYAML(texture, 0, data);
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-02-04 05:36:06 +00:00
|
|
|
/**
|
|
|
|
* [addSpriteSheet description]
|
|
|
|
* @param {[type]} key [description]
|
|
|
|
* @param {[type]} source [description]
|
|
|
|
* @param {[type]} config [description]
|
|
|
|
* @param {number} config.frameWidth - The fixed width of each frame.
|
|
|
|
* @param {number} [config.frameHeight] - The fixed height of each frame. If not set it will use the frameWidth as the height.
|
|
|
|
* @param {number} [config.startFrame=0] - Skip a number of frames. Useful when there are multiple sprite sheets in one Texture.
|
|
|
|
* @param {number} [config.endFrame=-1] - The total number of frames to extract from the Sprite Sheet. The default value of -1 means "extract all frames".
|
|
|
|
* @param {number} [config.margin=0] - If the frames have been drawn with a margin, specify the amount here.
|
|
|
|
* @param {number} [config.spacing=0] - If the frames have been drawn with spacing between them, specify the amount here.
|
|
|
|
*/
|
|
|
|
addSpriteSheet: function (key, source, config)
|
2016-12-06 16:18:28 +00:00
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
var width = texture.source[0].width;
|
|
|
|
var height = texture.source[0].height;
|
|
|
|
|
2017-02-04 05:36:06 +00:00
|
|
|
Parser.SpriteSheet(texture, 0, 0, 0, width, height, config);
|
2016-12-06 16:18:28 +00:00
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-04-11 16:22:22 +00:00
|
|
|
addSpriteSheetFromAtlas: function (key, config)
|
2016-12-06 16:18:28 +00:00
|
|
|
{
|
2017-04-26 15:03:14 +00:00
|
|
|
var atlasKey = GetValue(config, 'atlas', null);
|
|
|
|
var atlasFrame = GetValue(config, 'frame', null);
|
2017-04-11 16:22:22 +00:00
|
|
|
|
|
|
|
if (!atlasKey || !atlasFrame)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-06 16:18:28 +00:00
|
|
|
var atlas = this.get(atlasKey);
|
|
|
|
var sheet = atlas.get(atlasFrame);
|
|
|
|
|
|
|
|
if (sheet)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, sheet.source.image);
|
|
|
|
|
2017-04-18 14:31:30 +00:00
|
|
|
if (sheet.trimmed)
|
|
|
|
{
|
2017-11-03 13:15:58 +00:00
|
|
|
// If trimmed we need to help the parser adjust
|
2017-04-18 14:31:30 +00:00
|
|
|
Parser.SpriteSheetFromAtlas(texture, sheet, config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Parser.SpriteSheet(texture, 0, sheet.cutX, sheet.cutY, sheet.cutWidth, sheet.cutHeight, config);
|
|
|
|
}
|
2016-12-06 16:18:28 +00:00
|
|
|
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
addAtlasStarlingXML: function (key, source, data)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
if (Array.isArray(data))
|
|
|
|
{
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
{
|
|
|
|
Parser.StarlingXML(texture, i, data[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Parser.StarlingXML(texture, 0, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
|
|
|
addAtlasPyxel: function (key, source, data)
|
|
|
|
{
|
|
|
|
var texture = this.create(key, source);
|
|
|
|
|
|
|
|
if (Array.isArray(data))
|
|
|
|
{
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
{
|
|
|
|
Parser.Pyxel(texture, i, data[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Parser.Pyxel(texture, 0, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-05-10 23:36:11 +00:00
|
|
|
create: function (key, source, width, height)
|
2016-12-06 16:18:28 +00:00
|
|
|
{
|
2017-05-10 23:36:11 +00:00
|
|
|
var texture = new Texture(this, key, source, width, height);
|
2016-12-06 16:18:28 +00:00
|
|
|
|
|
|
|
this.list[key] = texture;
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
|
|
|
exists: function (key)
|
|
|
|
{
|
|
|
|
return (this.list.hasOwnProperty(key));
|
|
|
|
},
|
|
|
|
|
|
|
|
get: function (key)
|
|
|
|
{
|
|
|
|
if (key === undefined) { key = '__DEFAULT'; }
|
|
|
|
|
|
|
|
if (this.list[key])
|
|
|
|
{
|
|
|
|
return this.list[key];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this.list['__MISSING'];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
cloneFrame: function (key, frame)
|
|
|
|
{
|
|
|
|
if (this.list[key])
|
|
|
|
{
|
|
|
|
return this.list[key].get(frame).clone();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getFrame: function (key, frame)
|
|
|
|
{
|
|
|
|
if (this.list[key])
|
|
|
|
{
|
|
|
|
return this.list[key].get(frame);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-01-19 16:29:55 +00:00
|
|
|
getTextureKeys: function ()
|
|
|
|
{
|
|
|
|
var output = [];
|
|
|
|
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
if (key !== '__DEFAULT' && key !== '__MISSING')
|
|
|
|
{
|
|
|
|
output.push(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
},
|
|
|
|
|
2017-07-16 11:44:45 +00:00
|
|
|
getPixel: function (x, y, key, frame)
|
|
|
|
{
|
|
|
|
var textureFrame = this.getFrame(key, frame);
|
|
|
|
|
|
|
|
if (textureFrame)
|
|
|
|
{
|
|
|
|
var source = textureFrame.source.image;
|
|
|
|
|
|
|
|
if (x >= 0 && x <= source.width && y >= 0 && y <= source.height)
|
|
|
|
{
|
|
|
|
x += textureFrame.cutX;
|
|
|
|
y += textureFrame.cutY;
|
|
|
|
|
|
|
|
// if (textureFrame.trimmed)
|
|
|
|
// {
|
|
|
|
// x -= this.sprite.texture.trim.x;
|
|
|
|
// y -= this.sprite.texture.trim.y;
|
|
|
|
// }
|
|
|
|
|
|
|
|
var context = this._tempContext;
|
|
|
|
|
|
|
|
context.clearRect(0, 0, 1, 1);
|
|
|
|
context.drawImage(source, x, y, 1, 1, 0, 0, 1, 1);
|
|
|
|
|
|
|
|
var rgb = context.getImageData(0, 0, 1, 1);
|
|
|
|
|
|
|
|
return new Color(rgb.data[0], rgb.data[1], rgb.data[2], rgb.data[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
2016-12-06 16:18:28 +00:00
|
|
|
setTexture: function (gameObject, key, frame)
|
|
|
|
{
|
|
|
|
if (this.list[key])
|
|
|
|
{
|
|
|
|
gameObject.texture = this.list[key];
|
|
|
|
gameObject.frame = gameObject.texture.get(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
return gameObject;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Passes all Textures to the given callback.
|
|
|
|
*
|
|
|
|
* @method each
|
|
|
|
* @param {function} callback - The function to call.
|
|
|
|
* @param {object} [thisArg] - Value to use as `this` when executing callback.
|
|
|
|
* @param {...*} [arguments] - Additional arguments that will be passed to the callback, after the child.
|
|
|
|
*/
|
|
|
|
each: function (callback, thisArg)
|
|
|
|
{
|
|
|
|
var args = [ null ];
|
|
|
|
|
|
|
|
for (var i = 1; i < arguments.length; i++)
|
|
|
|
{
|
|
|
|
args.push(arguments[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var texture in this.list)
|
|
|
|
{
|
|
|
|
args[0] = this.list[texture];
|
|
|
|
|
|
|
|
callback.apply(thisArg, args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-04 12:23:58 +00:00
|
|
|
});
|
2016-12-06 16:18:28 +00:00
|
|
|
|
|
|
|
module.exports = TextureManager;
|