/** * Created by aghassaei on 1/16/15. */ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'materialsPlist', 'three', 'threeModel', 'latticeBase', 'console'], function(_, Backbone, appState, globals, plist, materialsPlist, THREE, three, LatticeBase, myConsole){ var Lattice = LatticeBase.extend({ defaults: _.extend(_.clone(LatticeBase.prototype.defaults), { units: "mm", scale: 1.0, cellType: "cube", connectionType: "gik", applicationType: "willGik", partType: null, aspectRatio: null, overlappingCells: [], nodes: [] }), __initialize: function(){ this.listenTo(this, "change:partType", this._updatePartType); this.listenTo(this, "change:cellType", function(){ var cellType = this.getCellType(); myConsole.clear(); myConsole.write("lattice.setCellType('" + cellType + "')"); this._cellTypeChanged(cellType); this.reloadCells(); }); this.listenTo(this, "change:connectionType", function(){ var connectionType = this.getConnectionType(); myConsole.clear(); myConsole.write("lattice.setConnectionType('" + connectionType + "')"); this._connectionTypeChanged(connectionType); this.reloadCells(); }); this.listenTo(this, "change:applicationType", function(){ var applicationType = this.getApplicationType(); myConsole.write("lattice.setApplicationType('" + applicationType + "')"); this._applicationTypeChanged(applicationType); this.reloadCells(); }); this.listenTo(this, "change:aspectRatio", function(){ var aspectRatio = this.getAspectRatio(); myConsole.write("lattice.setAspectRatio(" + aspectRatio.x + ", " + aspectRatio.y + ", " + aspectRatio.z +")"); this.reloadCells(); }); this.listenTo(appState, "change:currentNav", this._navChanged); this.listenTo(this, "change:cellsMin change:cellsMax", function(){ this.updateThreeViewTarget(); }); this._applicationTypeChanged(); this.reloadCells(); }, //getters getUnits: function(){ return this.get("units"); }, getScale: function(){ return this.get("scale"); }, getAspectRatio: function(){ return this.get("aspectRatio").clone(); }, getCellType: function(){ return this.get("cellType"); }, getConnectionType: function(){ return this.get("connectionType"); }, getApplicationType: function(){ return this.get("applicationType"); }, getPartType: function(){ return this.get("partType"); }, //setters setProperty: function(property, value, silent){ var changed = this.get(property) != value; if (silent !== true) silent = false; this.set(property, value, {silent:silent}); return changed; }, _getSetterName: function(property){ return "set" + property.charAt(0).toUpperCase() + property.slice(1); }, setAspectRatio: function(aspectRatio, silent){ if (!aspectRatio.x || !aspectRatio.y || !aspectRatio.z || aspectRatio.x<0 || aspectRatio.y<0 || aspectRatio.z<0) {//no 0, undefined, null, or neg #'s myConsole.warn("invalid aspect ratio params, lattice.setAspectRatio operation cancelled"); return; } return this.setProperty("aspectRatio", new THREE.Vector3(aspectRatio.x, aspectRatio.y, aspectRatio.z), silent); }, setCellType: function(cellType, silent){ if (plist.allLattices[cellType] === undefined){ myConsole.warn("no cell type " + cellType + ", lattice.setCellType operation cancelled"); return; } return this.setProperty("cellType", cellType, silent); }, setConnectionType: function(connectionType, silent){ var cellType = this.get("cellType"); var plistCellData = plist.allLattices[cellType]; if (plistCellData.connection[connectionType] === undefined){ myConsole.warn("no connection type " + connectionType + " for cell type " + cellType + ", lattice.setConnectionType operation cancelled"); return; } return this.setProperty("connectionType", connectionType, silent); }, setApplicationType: function(applicationType, silent){ var cellType = this.get("cellType"); var plistCellData = plist.allLattices[cellType]; var connectionType = this.get("connectionType"); var plistConnectionData = plistCellData.connection[connectionType]; if (plistConnectionData.type[applicationType] === undefined){ myConsole.warn("no application type " + applicationType + " for cell type " + cellType + " and connection type " + connectionType + ", lattice.setApplicationType operation cancelled"); return; } return this.setProperty("applicationType", applicationType, silent); }, setPartType: function(partType, silent){ var cellType = this.get("cellType"); var plistCellData = plist.allLattices[cellType]; var connectionType = this.get("connectionType"); var plistConnectionData = plistCellData.connection[connectionType]; var applicationType = this.get("applicationType"); var plistAppData = plistConnectionData.type[applicationType]; if (plistAppData.parts[partType] === undefined){ myConsole.warn("no part type " + partType + " for cell type " + plistCellData.name + " and connection type " + plistConnectionData.name + " and application type " + plistAppData.name + ", lattice.setPartType operation cancelled"); return; } myConsole.write("lattice.setPartType('" + partType + "')"); return this.setProperty("partType", partType, silent); }, setLatticeMetaData: function(data){ if (!data) { console.warn("no data received"); return; } var changed = false; var self = this; _.each(data, function(val, key){ if (self[self._getSetterName(key)]) { changed |= self[self._getSetterName(key)](val, true); } else console.warn("no setter found for param " + key); }); if (changed){ //todo trigger event } }, reloadCells: function(){ this.setSparseCells(this.sparseCells); }, setSparseCells: function(cells){ if (cells === undefined || cells == null) { console.warn("no cells given to setSparseCells"); return; } myConsole.clear(); var cellsString = JSON.stringify(cells); myConsole.write("lattice.setCells(" + cellsString + ")"); this._setSparseCells(JSON.parse(cellsString), this._getSubclassForLatticeType()); }, _getSubclassForLatticeType: function(){ var cellType = this.get("cellType"); var connectionType = this.get("connectionType"); var subclass = plist.allLattices[cellType].connection[connectionType].subclass; if (subclass === undefined){ console.warn("unrecognized cell type " + cellType); return null; } return subclass; }, _setSparseCells: function(cells, subclass){ if ((this.get("connectionType") == "gik" || this.previous("connectionType") == "gik") && this.get("applicationType") != this.previous("applicationType")) this.clearCells(); this._setDefaultCellMode();//cell mode var cellsMin = this.get("cellsMin"); var cellsMax = this.get("cellsMax"); var numCells = this.get("numCells"); this._clearCells(); if (this._undo) this._undo();//undo subclass methods if (globals.basePlane) globals.basePlane.destroy(); if (globals.highlighter) globals.highlighter.destroy(); if (cellsMax && cellsMin) this._expandCellsMatrix(cellsMax, cellsMin); var self = this; require([subclass], function(subclassObject){ _.extend(self, subclassObject); self._initLatticeType();//init for lattice subclass if (numCells > 0) { self._bindRenderToNumCells(numCells); self.parseCellsJSON(cells); } }); }, _setDefaultCellMode: function(){//if no part associated with this lattice type set to cell mode var latticeData = this._getLatticePlistData(); if (latticeData.parts === undefined){ var currentMode = appState.get("cellMode"); if (currentMode == "cell" || currentMode == "supercell") return; appState.set("cellMode", "cell"); } }, //latticeType _cellTypeChanged: function(cellType){ if (plist.allLattices[cellType].connection[this.getConnectionType()] === undefined){ var connectionType = _.keys(plist.allLattices[cellType].connection)[0]; this.set("connectionType", connectionType, {silent:true}); } this._connectionTypeChanged(); }, _connectionTypeChanged: function(connectionType){ if (connectionType === undefined) connectionType = this.getConnectionType(); var cellType = this.get("cellType"); var appType = _.keys(plist.allLattices[cellType].connection[connectionType].type)[0]; this.set("applicationType", appType, {silent:true}); this._applicationTypeChanged(appType); }, _applicationTypeChanged: function(applicationType){ var latticeData = this._getLatticePlistData(); this.set("aspectRatio", latticeData.aspectRatio.clone(), {silent:true}); var newPartType = null; if (latticeData.parts) newPartType = _.keys(latticeData.parts)[0]; this.set("partType", newPartType, {silent:true}); var newMaterialClass = (latticeData.materialClasses || _.keys(materialsPlist.allMaterialClasses))[0]; appState.set("materialClass", newMaterialClass); if (latticeData.options){ if (latticeData.options.gikLength) appState.set("gikLength", latticeData.options.gikLength); } }, xScale: function(){ return this.get("aspectRatio").x; }, yScale: function(){ return this.get("aspectRatio").y; }, zScale: function(){ return this.get("aspectRatio").z; }, //events __clearCells: function(silent){ three.removeAllCells();//todo add flag in cell destroy to avoid redundancy here this.set("nodes", [], {silent:silent}); if (globals.basePlane) globals.basePlane.set("zIndex", 0, {silent:silent}); }, updateThreeViewTarget: function(target){ if (target) { globals.threeView.setOrbitControlsFor(target); return; } if (!appState.get("focusOnLattice")) return; var cellsMin = this.get("cellsMin"); var cellsMax = this.get("cellsMax"); if (cellsMax === null || cellsMin === null) return; var center = cellsMax.clone().sub(cellsMin).divideScalar(2).add(cellsMin); if (globals.threeView && this.getPositionForIndex) globals.threeView.setOrbitControlsFor(this.getPositionForIndex(center)); }, //3d ui addHighlightableCell: function(cell){ three.addCell(cell); }, removeHighlightableCell: function(cell){ three.removeCell(cell); }, getHighlightableCells: function(){ return three.getCells(); }, //composite Cells _navChanged: function(){ var currentNav = appState.get("currentNav"); if (currentNav != "navComposite" && this.compositeEditor) this.exitCompositeEditing(); currentNav = plist.allMenus[currentNav].parent || currentNav; if (currentNav == "navSim" || currentNav == "navAssemble") this._parseSparseCell(); }, getCompositeData: function(){ if (this.get("numCells") == 0) return null; return { cellsMin: this.get("cellsMin").clone(), cellsMax: this.get("cellsMax").clone(), sparseCells: JSON.parse(JSON.stringify(this.sparseCells)), numCells: this.get("numCells") }; }, setToCompositeMode: function(compositeLattice){ this.compositeEditor = compositeLattice; }, inCompositeMode: function(){ return this.compositeEditor !== null && this.compositeEditor !== undefined; }, exitCompositeEditing: function(){ if (this.compositeEditor) this.compositeEditor.destroy(); this.compositeEditor = null; this.showCells(); }, getUItarget: function(){ if (this.inCompositeMode()) return this.compositeEditor; return this; }, reinitAllCellsOfTypes: function(types){//when material definition is changed this._loopCells(this.sparseCells, function(cell, x, y, z, self){ var material = cell.getMaterial(); if (material && material.isComposite() && types.indexOf(material.getID()) > -1){ //re-init cell; var json = cell.toJSON(); json.index = cell.getIndex(); self.makeCellWithJSON(json, function(newCell){ self.sparseCells[x][y][z] = newCell; cell.destroy(); }); } }); } }); var lattice = new Lattice(); appState.setLattice(lattice); return lattice; });