/** * Created by aghassaei on 1/16/15. */ ThreeView = Backbone.View.extend({ events: { "mousemove": "_mouseMoved", "mouseup": "_mouseUp", "mousedown": "_mouseDown", "mouseout": "_mouseOut" }, mouseIsDown: false,//store state of mouse click inside this el //intersections/object highlighting mouseProjection: new THREE.Raycaster(), highlighter: null, currentIntersectedPart: null, el: "#threeContainer", controls: null, initialize: function(options){ this.appState = options.appState; _.bindAll(this, "_animate", "_mouseMoved"); //bind events this.listenTo(this.appState, "change:deleteMode change:extrudeMode change:shift", this._setControlsEnabled); this.listenTo(dmaGlobals.lattice, "change:highlighter", this._saveHighlighter); this._saveHighlighter();//need a reference to the highlighter this.controls = new THREE.OrbitControls(this.model.camera, this.$el.get(0)); this.controls.addEventListener('change', this.model.render); this.$el.append(this.model.domElement);//render only once this.model.render(); this._animate(); }, //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////CONTROLS///////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// _animate: function(){ requestAnimationFrame(this._animate); this.controls.update(); }, _setControlsEnabled: function(){ var state = this.appState.get("deleteMode") || this.appState.get("shift") || this.appState.get("extrudeMode"); this.controls.enabled = !state; }, //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////MOUSE EVENTS///////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// _mouseOut: function(){ this.highlighter.setNothingHighlighted(); this._setNoPartIntersections(); }, _mouseUp: function(){ this.mouseIsDown = false; if (this.currentIntersectedPart) this.currentIntersectedPart.removeFromCell(); else this.highlighter.addRemoveVoxel(!this.appState.get("deleteMode")); }, _mouseDown: function(){ this.mouseIsDown = true; }, _mouseMoved: function(e){ if (this.mouseIsDown && this.controls.enabled) {//in the middle of a camera move this.highlighter.setNothingHighlighted(); this._setNoPartIntersections(); return; } //make projection vector var vector = new THREE.Vector2(2*(e.pageX-this.$el.offset().left)/this.$el.width()-1, 1-2*(e.pageY-this.$el.offset().top)/this.$el.height()); this.mouseProjection.setFromCamera(vector, this.model.camera); //check if we're in the same spot if (this.highlighter.isVisible()){ if(this.mouseProjection.intersectObject(this.highlighter.mesh, false).length > 0) return; } var intersections = this.mouseProjection.intersectObjects(this.model.cells.concat(this.model.basePlane), false); if (intersections.length == 0) {//no intersections this.highlighter.setNothingHighlighted(); this._setNoPartIntersections(); return; } this.highlighter.highlight(intersections[0]); if (this.mouseIsDown) { if (this.appState.get("deleteMode")){ this.highlighter.addRemoveVoxel(false); } else if (this.appState.get("shift")){ this.highlighter.addRemoveVoxel(true); } } if (this.appState.get("cellMode") == "part"){//additionally check for part intersections in part mode var partIntersections = this.mouseProjection.intersectObjects(this.model.parts, false); if (partIntersections.length == 0) { this._setNoPartIntersections(); return; } this._handlePartIntersections(partIntersections, intersections[0].distance); } }, //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////INTERSECTIONS//////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// _saveHighlighter: function(){ this.highlighter = dmaGlobals.lattice.get("highlighter"); }, _setNoPartIntersections: function(){ if (this.currentIntersectedPart){ this.currentIntersectedPart.unhighlight(); this.currentIntersectedPart = null; dmaGlobals.three.render(); } }, _handlePartIntersections: function(intersections, distanceToNearestCell){ var part = intersections[0].object.myPart; if (this.highlighter.isVisible() && intersections[0].distance > distanceToNearestCell){ this._setNoPartIntersections(); return; } this.highlighter.hide(); if (part!= this.currentIntersectedPart){ if (this.currentIntersectedPart) this.currentIntersectedPart.unhighlight(); part.highlight(); this.currentIntersectedPart = part; dmaGlobals.three.render(); } } });