/* global Palette */
/**
* @classdesc
* A Factory class designed to process objects, URLs, JSON and potentially other formats to generate
* valid {@link Palette.Shader} objects.
*
* This is a deliberate choice, to abstract some functionality away from the central {@link Palette.Manager}
* class.
* @class Palette.ShaderFactory
* @description Create a new ShaderFactory object - this is done automatically by {@link Palette.Manager}.
* @param {Palette.Manager} manager - The manager object to place generated shaders into.
* @author FelixMcFelix (Kyle S.)
*/
Palette.ShaderFactory = function(manager){
/**
* An object reference to the parent {@link Palette.Manager}.
* @name Palette.ShaderFactory#manager
* @type Palette.Manager
* @readonly
* @protected
*/
this.that = this;
this.manager = manager;
this.downloadInProgress = false;
};
Palette.ShaderFactory.prototype = {
/**
* Begin the shader construction process.
* @method Palette.ShaderFactory#addShader
* @public
* @param {string|Palette.Shader|Object} shader - URL, JSON, Shader Source Object or {@link Palette.Shader}.
*/
addShader: function(shader){
var inShader;
var outShader;
switch(this.establishType(shader)){
case Palette.ShaderFactory.SOURCE_OBJECT:
inShader = shader;
/* falls through */
case Palette.ShaderFactory.JSON:
inShader = inShader || JSON.parse(shader);
outShader = this.createShaderObject(inShader);
break;
case Palette.ShaderFactory.SHADER_OBJECT:
outShader = shader;
break;
case Palette.ShaderFactory.URL:
this.downloadFromURL(shader);
break;
default:
throw new Error("Not a valid type of shader.");
}
//while(this.downloadInProgress){}
if(outShader){this.registerShader(outShader);}
},
/**
* Create a shader from a source object.
* @method Palette.ShaderFactory#createShaderObject
* @protected
* @param {object} sourceObject - Either a list of shaders or a single shader object is valid.
* @return {Palette.Shader|null} Returns a {@link Palette.Shader} if the Source Object was not a list. If it was a list, it adds all the children instead.
*/
createShaderObject: function(sourceObject){
switch(sourceObject.type){
case Palette.Shader.VS:
case Palette.Shader.FS:
return new Palette.Shader(this.manager.context, sourceObject.name, sourceObject.type, sourceObject.src, sourceObject.attrs);
case Palette.Shader.LIST:
for (var i = sourceObject.content.length - 1; i >= 0; i--) {
this.addShader(sourceObject.content[i]);
}
break;
default:
throw new Error("Tried to create an illegal class of shader.");
}
},
/**
* Download a file from the supplied URL, before adding it to the manager.
* @method Palette.ShaderFactory#downloadFromURL
* @protected
* @param {string} url - URL corresponding to a Shader Source Object JSON file.
*/
downloadFromURL: function(url){
var rdr = new XMLHttpRequest();
rdr.open("GET", url, true);
rdr.onload = function(){
console.log(that);
that.addShader(rdr.response);
that.downloadInProgress = false;
};
that.downloadInProgress = true;
rdr.send();
},
/**
* Determine the type of shader reference passed to the factory.
* @method Palette.ShaderFactory#establishType
* @protected
* @param {string|Palette.Shader} shader - URL, JSON or Palette.Shader.
* @return {number} Either Palette.ShaderFactory.SOURCE_OBJECT, .JSON, .URL or .SHADER_OBJECT.
*/
establishType: function(shader){
var type = -1;
if(shader instanceof Palette.Shader){
type = Palette.ShaderFactory.SHADER_OBJECT;
} else if((shader.type != undefined) && (shader.name != undefined) && (shader.content || shader.src)){
type = Palette.ShaderFactory.SOURCE_OBJECT;
} else if(this.isJSON(shader)){
type = Palette.ShaderFactory.JSON;
/*} else if(this.isString(shader)){
type = Palette.ShaderFactory.URL;
}*/
}else{
console.log("PALETTE: BAD SHADER. MALFORMED JSON OR BAD OBJECT SHAPE.");
}
return type;
},
/**
* Determine if a string is valid JSON.
* @method Palette.ShaderFactory#isJSON
* @private
* @param {string} str - Suspected JSON string to check.
*/
isJSON: function(str){
try{
JSON.parse(str);
return true;
} catch (e){
return false;
}
},
isString: function(s){
return typeof(s) === 'string' || s instanceof String;
},
/**
* Add a shader directly into the manager's storage for future access.
* @method Palette.ShaderFactory#registerShader
* @protected
* @param {Palette.Shader} shaderObject - Compiled shader object to store in the {@link Palette.Manager}.
*/
registerShader: function(shaderObject){
switch(shaderObject.type){
case Palette.Shader.VS:
this.manager.vertShaders[shaderObject.name] = this.manager.vertShaders[shaderObject.name] || shaderObject;
break;
case Palette.Shader.FS:
this.manager.fragShaders[shaderObject.name] = this.manager.fragShaders[shaderObject.name] || shaderObject;
break;
default:
throw new Error("Tried to register an illegal class of shader.");
}
}
};
Palette.ShaderFactory.SOURCE_OBJECT = 0;
Palette.ShaderFactory.JSON = 1;
Palette.ShaderFactory.URL = 2;
Palette.ShaderFactory.SHADER_OBJECT = 3;
Palette.ShaderFactory.prototype.constructor = Palette.ShaderFactory;