Skip to content
Snippets Groups Projects
DMAMaterials.js 8.88 KiB
/**
 * Created by aghassaei on 6/4/15.
 */

//everything is a top level material with a threeMaterial object
define(['underscore', 'three', 'appState', 'lattice', 'plist', 'threeModel'], function(_, THREE, appState, lattice, plist, three){

    var materialsList = {
        deleteMaterial: {
            color: "#ff0000",
            threeMaterial: makeMaterialObject("#ff0000"),
            noDelete: true
        }
    };

    var listener = {};
    _.extend(listener, Backbone.Events);

    listener.listenTo(appState, "change:realisticColorScheme", changeColorScheme);
    listener.listenTo(appState, "change:materialClass", function(){setToDefaultMaterial()});//pass no params
    listener.listenTo(lattice, "change:connectionType cellType", function(){setToDefaultMaterial()});
    listener.listenTo(appState, "change:materialType", setMaterialDefaults);

    setToDefaultMaterial();





    function setMaterial(id, data){
        if (id && data === null) return deleteMaterial(id);
        if (!materialsList[id]) materialsList[id] = {};

        //check if colors have changed
        var oldColor = materialsList[id].color;
        var oldAltColor = materialsList[id].altColor;

        var edited = false;
        if (materialsList[id].sparseCells) edited = !(_.isEqual(data.sparseCells, materialsList[id].sparseCells));

        if (data.elementaryChildren) data.properties = getPropertiesFromChildren(data.elementaryChildren);

        _.each(_.keys(data), function(key){
            if (data[key] && data[key].x) materialsList[id][key] = new THREE.Vector3(data[key].x, data[key].y, data[key].z);
            else materialsList[id][key] = data[key];
        });

        if (!materialsList[id].threeMaterial || oldColor != materialsList[id].color || oldAltColor != materialsList[id].altColor) changeSingleMaterialColorScheme(id);
        if (edited){
            var allChangedMaterialsList = getAllParentComposites(id);
            allChangedMaterialsList.push(id);

            _.each(allChangedMaterialsList, function(key){
                materialsList[key].compositeChildren = getChildCellTypes(materialsList[key].sparseCells, false);
                materialsList[key].elementaryChildren = getChildCellTypes(materialsList[key].sparseCells, true);
            });

            lattice.reinitAllCellsOfTypes(allChangedMaterialsList);
        }

        return false;
    }

    function deleteMaterial(id){
        if (materialsList[id].noDelete) {
            console.warn("no delete flag on this material type");
            return false;
        }
        delete materialsList[id];//todo check if being used first (instances)
        var deleted = true;
        if (deleted) setToDefaultMaterial();
        return deleted;
    }

    function getMaterialForId(id){
        return materialsList[id];
    }









    function getCompositeKeys(){
        return _.filter(_.keys(materialsList), function(key){
            return key.substr(0,5) == "super";
        });
    }

    function getVaildAvailableCompositeKeys(id){//for "available materials" list in composite editor
        var compositeKeys = getCompositeKeys();
        var invalidKeys = getAllParentComposites(id);
        invalidKeys.push(id);
        return _.difference(compositeKeys, invalidKeys);
    }

    function getAllParentComposites(id){
        var parentComposites = [];
        _.each(materialsList, function(material, key){
            if (key == id) return;
            if (material.compositeChildren && material.compositeChildren.indexOf(id)>-1){
                parentComposites.push(key);
            }
        });
        return parentComposites;
    }

    function getChildCellTypes(cells, elementaryTypes){//deep search to find all sub sub components
        var children = [];
        loopCells(cells, function(cell){
            if (!cell) return;
            var isComposite = cell.materialName.substr(0,5) == "super";
            if ((elementaryTypes && !isComposite) || (!elementaryTypes && isComposite)) children.push(cell.materialName);
            if (isComposite){
                if (elementaryTypes && materialsList[cell.materialName].elementaryChildren) {
                    Array.prototype.push.apply(children, materialsList[cell.materialName].elementaryChildren);
                }
                else if (!elementaryTypes && materialsList[cell.materialName].compositeChildren) {
                    Array.prototype.push.apply(children, materialsList[cell.materialName].compositeChildren);
                }
            }
        });
        if (children.length == 0) return null;
        return _.uniq(children);//remove duplicates
    }

    function getPropertiesFromChildren(children){
        var properties = {};
        _.each(children, function(child){
            if (materialsList[child].properties.conductive) properties.conductive = true;
        });
        return properties;
    }

    function loopCells(cells, callback){
        for (var x=0;x<cells.length;x++){
            for (var y=0;y<cells[0].length;y++){
                for (var z=0;z<cells[0][0].length;z++){
                    callback(cells[x][y][z], x, y, z);
                }
            }
        }
    }













    function setToDefaultMaterial(triggerEvent){
        var materialClass = appState.get("materialClass");
        var newDefaultType = _.keys(plist.allMaterials[materialClass])[0];
        if (!materialsList[newDefaultType]) _.extend(materialsList, parseClassFromDefinitions(plist.allMaterials[materialClass]));
        if (!materialsList[newDefaultType]) console.warn("material type " + newDefaultType + "  not in definition for " + materialClass);
        if (triggerEvent === undefined) triggerEvent = false;
        appState.set("materialType", newDefaultType, {silent:!triggerEvent});
    }

    function parseClassFromDefinitions(definitions){
        var newMaterials = {};
        var state = appState.get("realisticColorScheme");
        _.each(_.keys(definitions), function(key){
            newMaterials[key] = definitions[key];
            var color = getMaterialColorForState(state, definitions[key], key);
            newMaterials[key].threeMaterial = makeMaterialObject(color);
            newMaterials[key].transparentMaterial = makeMaterialObject(color, true);
            newMaterials[key].noDelete = true;//don't delete the predefined materials
        });
        return newMaterials;
    }









    function changeColorScheme(){
        var state = appState.get("realisticColorScheme");
        _.each(_.keys(materialsList), function(name){
            if (name == "setMaterial") return;
            changeSingleMaterialColorScheme(name, state);
        });
        three.render();
    }

    function changeSingleMaterialColorScheme(name, state){
        if (!state) state = appState.get("realisticColorScheme");
        var materialInfo = materialsList[name];
        var color = getMaterialColorForState(state, materialInfo, name);

        if (materialInfo.threeMaterial) materialInfo.threeMaterial.color = new THREE.Color(color);
        else materialInfo.threeMaterial = makeMaterialObject(color);

        if (materialInfo.transparentMaterial) materialInfo.transparentMaterial.color = new THREE.Color(color);
        else materialInfo.transparentMaterial = makeMaterialObject(color, true);
    }
    function getMaterialColorForState(state, definition, key){
        var color = definition.color;
        if (!color) console.warn("no color for material type " + key);
        if (!state && definition.altColor) color = definition.altColor;
        return color;
    }

    function makeMaterialObject(color, transparent){
        if (transparent) return new THREE.MeshLambertMaterial({color:color, shading:THREE.FlatShading, transparent: true, opacity:0.1});
        return new THREE.MeshLambertMaterial({color:color, shading:THREE.FlatShading});
    }

    function setMaterialDefaults(){
        var materialType = appState.get("materialType");
        appState.set("superCellIndex", new THREE.Vector3(0,0,0));
        if (materialsList[materialType].dimensions){
            appState.set("superCellRange", materialsList[materialType].dimensions.clone());
        } else if (lattice.get("connectionType") == "gik"){
            appState.set("superCellRange", new THREE.Vector3(appState.get("gikLength"), 1, 1));
        }
    }





    //edit material definition

    var editingMaterial = null;//material definition currently being edited

    function setEditingMaterial(id){
        editingMaterial = id;
    }

    function getEditingMaterial(){
        return editingMaterial;
    }






    return {
        list: materialsList,
        setMaterial: setMaterial,
        getMaterialForId: getMaterialForId,
        getCompositeKeys: getCompositeKeys,
        getVaildAvailableCompositeKeys: getVaildAvailableCompositeKeys,
        getChildCellTypes:getChildCellTypes,
        setToDefaultMaterial: setToDefaultMaterial,
        setEditingMaterial: setEditingMaterial,
        getEditingMaterial: getEditingMaterial
    };
});