FelixMcFelix/laughing-ironman

View on GitHub
src/Palette/ShaderFactory.js

Summary

Maintainability
A
2 hrs
Test Coverage
/* 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;