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