Engine.GraphicLoader = class {
constructor() {}
load(url, callback, errorCallback)
{
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[url].data, callback, errorCallback);});
}
jsonLoaded(url, data, callback, errorCallback)
{
var t = this;
if (data == null)
{
Debug.Log("Loaded data was null for:"+url);
if (errorCallback != null) errorCallback();
return;
}
var format = data.format;
if (format == "spritesheet")
{
var loader = new Engine.SpriteSheetLoader();
loader.OnLoaded = function(){t.loaderComplete(loader, callback)};
loader.OnError = errorCallback;
loader.jsonLoaded(url, data);
}
if (format == "skeletal")
{
var loader = new Engine.SkeletalLoader();
loader.OnLoaded = function(){t.loaderComplete(loader, callback)};
loader.OnError = errorCallback;
loader.jsonLoaded(url, data);
}
if (format == "scene")
{
var loader = new Engine.SceneLoader();
loader.OnLoaded = function(){t.loaderComplete(loader, callback)};
loader.OnError = errorCallback;
loader.jsonLoaded(url, data);
}
}
loaderComplete(loader, graphicLoaderCallback)
{
graphicLoaderCallback(loader.graphics);
}
}
Engine.JSONLoader = class {
constructor()
{
this.url = null;
this.data = null;
this.OnLoaded = null;
}
load(url, loadedCallback)
{
if (loadedCallback !== undefined) this.OnLoaded = loadedCallback;
this.url = url;
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[t.url].data);});
}
jsonLoaded(url, data)
{
var t = this;
this.url = url;
this.data = data;
if (this.OnLoaded) this.OnLoaded(t);
}
}
Engine.TextureLoader = class {
constructor()
{
this.url = null;
this.data = null;
this.files = [];
this.baseTextures = [];
this.namePrefix = "";
this.OnLoaded = null;
this.graphics;
}
load(url)
{
this.url = url;
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[t.url].data);});
}
jsonLoaded(url, data)
{
var t = this;
this.url = url;
this.data = data;
this.files = this.data.files;
var loader = new PIXI.Loader();
var urlRoot = this.url.substr(0,this.url.lastIndexOf("/") + 1);
var version = this.url.indexOf("?") != -1 ? this.url.substring(this.url.lastIndexOf("?"), this.url.length) : "";
for (var i = 0; i < this.files.length; i++)
{
this.files[i] = urlRoot + this.files[i] + version;
if (loader.resources[this.files[i]])
{
Debug.Log("Resource:"+this.files[i]+" Already Loaded...");
} else {
loader.add(this.files[i]);
}
}
loader.load(function(){t.texturesLoaded(loader);});
}
texturesLoaded(loader)
{
var t = this;
for (var i = 0; i < this.files.length; i++)
{
this.baseTextures[i] = loader.resources[this.files[i]].texture.baseTexture;
}
var graphics = this.data.graphics;
var processedGraphics = {};
for (var i = 0; i < graphics.length; i++)
{
graphics[i].name = this.namePrefix + graphics[i].name;
var name = graphics[i].name;
var existingDef = Engine.GraphicFactoryInstance.getGraphicDataByName(name);
if (processedGraphics[name])
{
if (graphics[i].sizeX)
{
var sizeX = graphics[i].sizeX;
var sizeY = graphics[i].sizeY;
//this name already has a graphic set, try to update an existing alternate size.
var alternateSize = processedGraphics[name].getDefBySizeExactMatch(sizeX, sizeY);
//if no existing alternate size, create one.
if(!alternateSize)
{
alternateSize = new Engine.GraphicDef();
processedGraphics[name].addSizedSubDef(alternateSize);
}
alternateSize.setData(graphics[i], this.baseTextures, this.data.texture_scale);
}
} else {
// first load of this name, set or create def.
processedGraphics[name] = existingDef;
if (processedGraphics[name] == null) processedGraphics[name] = new Engine.GraphicDef();
processedGraphics[name].setData(graphics[i], this.baseTextures, this.data.texture_scale);
}
}
this.graphics = processedGraphics;
if (this.OnLoaded) this.OnLoaded(t);
}
}
Engine.SpriteSheetLoader = class {
constructor()
{
this.url = null;
this.data = null;
this.files = [];
this.baseTextures = [];
this.namePrefix = "";
this.OnLoaded = null;
this.OnError = null;
this.graphics;
}
load(url)
{
this.url = url;
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[t.url].data);});
}
jsonLoaded(url, data)
{
if (data == null)
{
if (this.OnError != null) this.OnError();
return;
}
var t = this;
this.url = url;
this.data = data;
this.files = this.data.files;
var loader = new PIXI.Loader();
var urlRoot = this.url.substr(0,this.url.lastIndexOf("/") + 1);
var version = this.url.indexOf("?") != -1 ? this.url.substring(this.url.lastIndexOf("?"), this.url.length) : "";
for (var i = 0; i < this.files.length; i++)
{
this.files[i] = urlRoot+this.files[i]+version;
if (loader.resources[this.files[i]])
{
Debug.Log("Resource:"+this.files[i]+" Already Loaded...");
} else {
loader.add(this.files[i]);
}
}
loader.load(function(){t.texturesLoaded(loader);});
}
texturesLoaded(loader)
{
var t = this;
for (var i = 0; i < this.files.length; i++)
{
this.baseTextures[i] = loader.resources[this.files[i]].texture.baseTexture;
}
var graphics = this.data.graphics;
var processedGraphics = {};
for (var i = 0; i < graphics.length; i++)
{
graphics[i].name = this.namePrefix + graphics[i].name;
var name = graphics[i].name;
var existingDef = Engine.GraphicFactoryInstance.getGraphicDataByName(name);
if (processedGraphics[name])
{
if (graphics[i].sizeX)
{
var sizeX = graphics[i].sizeX;
var sizeY = graphics[i].sizeY;
//this name already has a graphic set, try to update an existing alternate size.
var alternateSize = processedGraphics[name].getDefBySizeExactMatch(sizeX, sizeY);
//if no existing alternate size, create one.
if(!alternateSize)
{
alternateSize = new Engine.GraphicDef();
processedGraphics[name].addSizedSubDef(alternateSize);
}
alternateSize.setData(graphics[i], this.baseTextures, this.data.texture_scale);
}
} else {
// first load of this name, set or create def.
processedGraphics[name] = existingDef;
if (processedGraphics[name] == null) processedGraphics[name] = new Engine.GraphicDef();
processedGraphics[name].setData(graphics[i], this.baseTextures, this.data.texture_scale);
}
}
this.graphics = processedGraphics;
if(this.OnLoaded) this.OnLoaded(t);
}
}
Engine.SkeletalLoader = class {
constructor()
{
this.url = null;
this.data = null;
this.files = [];
this.baseTextures = [];
this.namePrefix = "";
this.OnLoaded = null;
this.OnError = null;
this.graphics;
}
load(url)
{
this.url = url;
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[t.url].data);});
}
jsonLoaded(url, data)
{
if (data == null)
{
if (this.OnError != null) this.OnError();
return;
}
var t = this;
this.url = url;
this.data = data;
this.files = this.data.files;
var loader = new PIXI.Loader();
var urlRoot = this.url.substr(0,this.url.lastIndexOf("/") + 1);
var version = this.url.indexOf("?") != -1 ? this.url.substring(this.url.lastIndexOf("?"), this.url.length) : "";
for (var i = 0; i < this.files.length; i++)
{
this.files[i] = urlRoot+this.files[i]+version;
if (loader.resources[this.files[i]])
{
Debug.Log("Resource:"+this.files[i]+" Already Loaded...");
} else {
loader.add(this.files[i]);
}
}
loader.load(function(){t.texturesLoaded(loader);});
}
texturesLoaded(loader)
{
var t = this;
for (var i = 0; i < this.files.length; i++)
{
this.baseTextures[i] = loader.resources[this.files[i]].texture.baseTexture;
}
var graphics = this.data.characters;
var processedGraphics = {};
for (var i = 0; i < graphics.length; i++)
{
graphics[i].name = this.namePrefix + graphics[i].name;
var name = graphics[i].name;
processedGraphics[name] = Engine.GraphicFactoryInstance.getGraphicDataByName(name);
if (processedGraphics[name] == null) processedGraphics[name] = new Engine.GraphicDef();
processedGraphics[name].setSkeletalData(graphics[i], this.baseTextures, this.data.texture_scale);
}
this.graphics = processedGraphics;
if(this.OnLoaded) this.OnLoaded(t);
}
}
Engine.SceneLoader = class {
constructor()
{
this.url = null;
this.data = null;
this.files = [];
this.baseTextures = [];
this.namePrefix = "";
this.OnLoaded = null;
this.OnError = null;
this.graphics = {};
}
load(url)
{
this.url = url;
var t = this;
var loader = new PIXI.Loader();
loader
.add(url)
.load(function(){t.jsonLoaded(url, loader.resources[t.url].data);});
}
jsonLoaded(url, data)
{
if (data == null)
{
if (this.OnError != null) this.OnError();
return;
}
var t = this;
this.url = url;
this.data = data;
this.data.name = this.namePrefix + this.data.name;
this.files = this.data.files;
var loader = new PIXI.Loader();
var urlRoot = this.url.substr(0,this.url.lastIndexOf("/") + 1);
var version = this.url.indexOf("?") != -1 ? this.url.substring(this.url.lastIndexOf("?"), this.url.length) : "";
this.data.graphic_asset;
this.data.skeletal_asset;
this.clips = this.data.clips;
for (var d of this.clips)
{
d.original_name = d.name;
d.name = this.data.name + "_" + d.name;
}
var sceneGraphic = new Engine.GraphicDef();
sceneGraphic = Engine.GraphicFactoryInstance.getGraphicDataByName(this.data.name);
if (sceneGraphic == null) sceneGraphic = new Engine.GraphicDef();
sceneGraphic.setSceneData(this.data);
this.graphics[sceneGraphic.name] = sceneGraphic;
this.waiting = 0;
if (this.data.graphic_asset)
{
var graphicLoader = new Engine.SpriteSheetLoader();
graphicLoader.namePrefix = this.data.name + "_";
graphicLoader.OnLoaded = function(){t.graphicsLoaded(graphicLoader)};
graphicLoader.load(urlRoot+this.data.graphic_asset+version, data);
this.waiting++;
}
if (this.data.skeletal_asset)
{
var skelLoader = new Engine.SkeletalLoader();
skelLoader.namePrefix = this.data.name + "_";
skelLoader.OnLoaded = function(){t.graphicsLoaded(skelLoader)};
skelLoader.load(urlRoot+this.data.skeletal_asset+version, data);
this.waiting++;
}
}
graphicsLoaded(loader)
{
for(var g in loader.graphics)
{
this.graphics[g] = loader.graphics[g];
}
this.waiting--;
if (this.waiting == 0)
{
var t = this;
if(this.OnLoaded) this.OnLoaded(t);
}
}
}
var GraphicDefStatics = {};
GraphicDefStatics.LoadState = {None: 0, Loaded: 1, Failed: 2};
GraphicDefStatics.blockLoadedCallbacks = 0;
GraphicDefStatics.needsCallbacks = new Set(); //GraphicDef;
GraphicDefStatics.blockLoadedCallbacks = function()
{
this.blockLoadedCallbacks++;
}
GraphicDefStatics.unblockLoadedCallbacks = function()
{
if (this.blockLoadedCallbacks > 0)
{
this.blockLoadedCallbacks--;
if (this.blockLoadedCallbacks == 0)
{
// copy the list...
var callbackList = Array.from(this.needsCallback);
this.needsCallbacks.clear();
for (var needsCallback /*GraphicDef*/ of callbackList)
{
needsCallback.setLoaded();
}
}
}
}
Engine.GraphicDef = class {
constructor(name, url)
{
this.type = "spritesheet";
this.name = name;
this.loadStatus = GraphicDefStatics.LoadState.None;
this._url = url;
this.sequences = [];
this.baseTextures = [];
this.cachedTextures = {};
this.frames = {};
this.id = -1;
this.size = new PIXI.Point(0,0);
this.isDefaultSize = true;
this.additionalSizes = [];
this.onLoaded = new Action();
this.onChange = new Action();
}
get loaded()
{
return this.loadStatus == GraphicDefStatics.LoadState.Loaded;
}
get url()
{
if (this._url !== undefined) return this._url;
return EngineSettings.AssetRoot + this.folder + "/" + this.name + ".json" + "?v=" + this.version;
}
readData(data)
{
this.id = data.id;
var index = data.graphic.lastIndexOf("/");
if (index != -1)
{
this.folder = data.graphic.substring(0, index + 1);
this.name = data.graphic.substring(index + 1);
}
else
{
this.name = data.graphic;
}
if (this.name.indexOf("Beard_Moustache") != -1){
var breakhere = true;
}
if (data.export_params.available_sizes)
{
var sizes = data.export_params.available_sizes;
for (var i = 0; i < sizes.length; i++)
{
//"available_sizes":["default","128x128"]
var split = sizes[i].split("x");
if (split.length == 2)
{
var def = new Engine.GraphicDef();
data.export_params.available_sizes = false;
def.readData(data);
def.size.x = split[0];
def.size.y = split[1];
this.additionalSizes.push(def);
}
}
this.isDefaultSize = true;
}
this.version = data.v;
this.type_id = data.type;
switch(data.type)
{
case 1: this.type = "spritesheet"; break;
case 3: this.type = "skeletal"; break;
case 6: this.type = "scene"; break;
}
}
setTextureMode(scaleMode)
{
//PIXI.SCALE_MODES.NEAREST
for (var i = 0; i < this.baseTextures.length; i++)
{
this.baseTextures[i].scaleMode = scaleMode;
}
}
/*getTexture(seq, frame)
{
var frameData = this.sequences[seq][frame];
let texture = new PIXI.Texture(this.baseTextures[frameData.texture]);
texture.frame = frameData.frame;
return texture;
}*/
/*getSprite(seq, frame)
{
var frameData = this.sequences[seq][frame];
let texture = new PIXI.Texture(this.baseTextures[frameData.texture]);
var sprite = new PIXI.Sprite(texture);
sprite.texture.frame = frameData.frame;
sprite.anchor.x = frame.pivot.x;
sprite.anchor.y = frame.pivot.y;
return sprite;
}*/
getNumFramesInSeq(seq)
{
if (seq >= 0 && this.sequences.length > seq)
{
if (this.type == "spritesheet") return this.sequences[seq].length;
if (this.type == "skeletal") return this.sequences[seq].length > 0 ? this.sequences[seq][0].sequence.length : 0;
}
return 0;
}
matchSprite(sprite, seq, frame)
{
if (this.loaded == false) return;
if (this.type != "spritesheet")
{
Debug.Log("Match Sprite Called on "+this.type);
return;
}
if (this.sequences.length > seq)
{
var numFrames = this.sequences[seq].length;
frame = frame % numFrames;
var frameData = this.sequences[seq][frame];
sprite.texture = this.getTexture(seq, frame);
sprite.texture.frame = frameData.frame;
if (sprite.anchor !== undefined)
{
sprite.anchor.x = frameData.pivot.x;
sprite.anchor.y = frameData.pivot.y;
}
}
}
getTexture(seq, frame)
{
var frameData = this.sequences[seq][frame];
if (!this.cachedTextures.containsKey(seq))
{
this.cachedTextures[seq] = {};
}
if (!this.cachedTextures[seq].containsKey(frame))
{
let texture = new PIXI.Texture(this.baseTextures[frameData.texture]);
this.cachedTextures[seq][frame] = texture;
}
return this.cachedTextures[seq][frame];
}
getDefBySizeExactMatch(width, height)
{
for (var i = 0; i < this.additionalSizes.length; i++)
{
if (this.additionalSizes[i].size.x == width && this.additionalSizes[i].size.y == height) return this.additionalSizes[i];
}
return null;
}
getAlternateDefBySize(width, height)
{
var minDifDef = this;
var minDif = Math.abs(this.size.x - width) + Math.abs(this.size.y - height);
for (var i = 0; i < this.additionalSizes.length; i++)
{
var size = this.additionalSizes[i].size;
var dif = Math.abs(size.x - width) + Math.abs(size.y - height);
if (dif < minDif)
{
minDifDef = this.additionalSizes[i];
minDif = dif;
}
}
return minDifDef;
}
addSizedSubDef(def)
{
//check to see if there is already a sized def associated with this def.
var existingDef = this.getDefBySizeExactMatch(def.size.x, def.size.y);
if (existingDef)
{
existingDef
} else {
this.additionalSizes.push(def);
}
}
loadFailed()
{
this.loadStatus = GraphicDefStatics.LoadState.Failed;
this.changed();
}
setLoaded()
{
this.loadStatus = GraphicDefStatics.LoadState.Loaded;
if (GraphicDefStatics.blockLoadedCallbacks > 0)
{
GraphicDefStatics.needsCallback.add(this);
}
else
{
this.onLoaded.call(this);
this.changed();
}
}
changed()
{
this.onChange.call(this);
}
setData(data, baseTextures, textureScale)
{
if (textureScale === undefined) textureScale = 1;
this.type = "spritesheet";
this.baseTextures = baseTextures;
for (var texture of baseTextures)
{
if (texture.resolution != textureScale)
{
texture.setResolution(textureScale);
//texture.update();
}
}
this.name = data.name;
this.sequences = [];
if (data.sizeX)
{
this.size.x = data.sizeX;
this.size.y = data.sizeY;
this.isDefaultSize = data.defaultSize;
}
for (var s = 0; s < data.sequences.length; s++)
{
var frames = data.sequences[s];
var processedFrames = [];
for (var f = 0; f < frames.length; f++)
{
let frame = {
frame: new PIXI.Rectangle(frames[f].tx, frames[f].ty, frames[f].tw, frames[f].th),
pivot:{x:(frames[f].x)/(frames[f].tw), y:(frames[f].y)/(frames[f].th)}, texture:frames[f].texture };
processedFrames.push(frame);
}
this.sequences.push(processedFrames);
}
this.setLoaded();
}
setSkeletalData(data, baseTextures, textureScale)
{
if (textureScale === undefined) textureScale = 1;
this.type = "skeletal";
this.baseTextures = baseTextures;
for (var texture of baseTextures)
{
texture.resolution = textureScale;
texture.update();
}
this.name = data.name;
this.sequences = [];
var textureFrames = {};
var sequences = data.sequences;
this.sequences = sequences;
var uniqueFrames = {};
for (var s = 0; s < sequences.length; s++)
{
var pieces = sequences[s];
for (var i = 0; i < pieces.length; i++)
{
var frameInfo = pieces[i];
var key = frameInfo.x+"_"+frameInfo.y+"_"+frameInfo.texture_index;
if (!uniqueFrames[key])
{
let frame = { frame: new PIXI.Rectangle(frameInfo.x, frameInfo.y, frameInfo.w, frameInfo.h), pivot:{x:frameInfo.cx/frameInfo.w, y:frameInfo.cy/frameInfo.h} };
textureFrames[key] = frame;
uniqueFrames[key] = true;
}
}
}
this.frames = textureFrames;
this.setLoaded();
}
setSceneData(data)
{
this.name = data.name;
this.setLoaded();
this.type = "scene";
this.clips = data.clips;
}
}
Engine.SkeletalAnimationController = class {
constructor(graphicDef)
{
this.graphicDef = graphicDef;
this.nextPieceCacheIndexes = [];
this.pieceCache = [];
for (var i = 0; i < graphicDef.baseTextures.length; i++)
{
this.pieceCache.push([]);
this.nextPieceCacheIndexes.push(0);
}
this.group = new PIXI.Container();
}
setFrame(sequence, frame)
{
if (Engine.Drawable.fastRenderMode) return;
//this.clearDebug();
this.clearUsedPieces();
if (!this.graphicDef) return;
this.pieces = this.graphicDef.sequences[sequence];
if (this.pieces === undefined){
Debug.LogError("Attempt to set non existant sequence "+sequence+" on "+this.graphicDef.name);
return;
}
for (var i = 0; i < this.pieces.length; i++)
{
var frameInfo = this.pieces[i].sequence[frame];
if (frameInfo === undefined){
Debug.LogError("Attempt to set non existant frame "+frame+" on "+this.graphicDef.name);
return;
}
if (frameInfo.used)
{
var piece = this.getPiece(this.pieces[i]);
var rot = frameInfo.rot;
var xScaleNeg = frameInfo.sx < 0;
var yScaleNeg = frameInfo.sy < 0;
if (xScaleNeg != yScaleNeg) rot *= -1;
piece.rotation = rot;
piece.x = frameInfo.tx;
piece.y = frameInfo.ty;
piece.z = frameInfo.z;
piece.zOrder = piece.z;
piece.scale.x = frameInfo.sx;
piece.scale.y = frameInfo.sy;
if (piece.parent != this.group) this.group.addChild(piece);
//this.addDebug(piece, frameInfo, this.pieces[i]);
}
}
this.group.children.sort((a, b) => {
if(a.zOrder === b.zOrder) return 0;
else return (a.zOrder < b.zOrder ? -1 : 1);
});
}
clearDebug()
{
if (this.activeDebug !== undefined){
for(var i = 0; i < this.activeDebug.length; i++){
this.activeDebug[i].parent.removeChild(this.activeDebug[i]);
}
this.activeDebug.length = 0;
}
}
addDebug(piece, frameInfo, pieceInfo)
{
if (pieceInfo.n && pieceInfo.n.indexOf("Unknown") == -1) {
//piece.visible = false;
return;
}
if (this.debugClips === undefined) {
this.debugClips = new Engine.ObjectPool(Engine.DrawableText);
this.activeDebug = [];
}
var clip = this.debugClips.getNextObject();
this.activeDebug.push(clip);
//clip.setText(pieceInfo.n +" "+frameInfo.tx+" "+frameInfo.ty, "Verdana", 24);
clip.setText(pieceInfo.n, "Verdana", 24);
clip.scale.x = 1/5;
clip.scale.y = 1/5;
piece.addChild(clip);
}
getPiece(pieceData)
{
var key = pieceData.x+"_"+pieceData.y+"_"+pieceData.texture_index;
var piece = null;
var textureIndex = pieceData.texture_index;
if (this.pieceCache == null) this.pieceCache = [];
if (this.pieceCache[pieceData.texture_index].length > this.nextPieceCacheIndexes[pieceData.texture_index])
{
piece = this.pieceCache[pieceData.texture_index][this.nextPieceCacheIndexes[pieceData.texture_index]];
} else {
let texture = new PIXI.Texture(this.graphicDef.baseTextures[pieceData.texture_index]);
piece = new PIXI.Sprite(texture);
this.pieceCache[pieceData.texture_index].push(piece);
}
if (piece.texture.frame.x != this.graphicDef.frames[key].frame.x || piece.texture.frame.y != this.graphicDef.frames[key].frame.y)
{
piece.texture.frame = this.graphicDef.frames[key].frame;
piece.anchor.x = this.graphicDef.frames[key].pivot.x;
piece.anchor.y = this.graphicDef.frames[key].pivot.y;
}
this.nextPieceCacheIndexes[pieceData.texture_index]++;
piece.visible = true;
return piece;
}
clearUsedPieces()
{
if (this.pieceCache == null) return;
for (var i = 0; i < this.pieceCache.length; i++)
{
this.nextPieceCacheIndexes[i] = 0;
for (var j = 0; j < this.pieceCache[i].length; j++)
{
this.pieceCache[i][j].visible = false;
}
}
}
destroy()
{
if (this.pieceCache != null)
{
for (var i = 0; i < this.pieceCache.length; i++)
{
this.nextPieceCacheIndexes[i] = 0;
for (var j = 0; j < this.pieceCache[i].length; j++)
{
if (this.pieceCache[i][j].parent != null) this.pieceCache[i][j].parent.removeChild(this.pieceCache[i][j]);
}
}
}
this.pieceCache = null;
this.graphicDef = null;
this.nextPieceCacheIndexes = null;
if (this.group.parent != null) this.group.parent.removeChild(this.group);
this.group = null;
}
}