/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ var Montage = require("montage/core/core").Montage, drawUtils = require("js/helper-classes/3D/draw-utils").DrawUtils, vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils, viewUtils = require("js/helper-classes/3D/view-utils").ViewUtils, snapManager = require("js/helper-classes/3D/snap-manager").SnapManager, Keyboard = require("js/mediators/keyboard-mediator").Keyboard; toolBase = require("js/tools/ToolBase").toolBase; exports.PanTool = Montage.create(toolBase, { _localPt :{value: [0,0] , writable:true}, _worldPt :{value: [0,0] , writable:true}, _globalPt :{value: [0,0] , writable:true}, _globalToUCWorld :{value: [] , writable:true}, _lastGPt :{value: [0,0], writable:true}, _lastY :{value: 0, writable:true}, Configure: { value: function ( doActivate ) { if (doActivate) { NJevent("enableStageMove"); this.eventManager.addEventListener( "toolDoubleClick", this, false); this.application.ninja.stage.canvas.addEventListener("mousewheel", this, false); this.activate(); } else { NJevent("disableStageMove"); this.eventManager.removeEventListener( "toolDoubleClick", this, false); this.application.ninja.stage.canvas.removeEventListener("mousewheel", this, false); this.deactivate(); } } }, HandleLeftButtonDown: { value : function ( event ) { this._isDrawing = true; this.isDrawing = true; this.mouseDown( event ); } }, HandleMouseMove: { value : function (event) { this.mouseMove( event ); } }, HandleLeftButtonUp: { value : function ( event ) { //if(this._isDrawing) { // do one final mouse move to update the scrollbars this.mouseUp( event ); this.application.ninja.stage.clearDrawingCanvas(); this._hasDraw = false; this._isDrawing = false; this.isDrawing = false; } } }, HandleKeyPress: { value: function(event) { if(event.altKey) { this._altKeyDown = true; } else if (event.shiftKey) { if (!this._shiftKeyDown) { this._shiftKeyDown = true; this._shiftPt = this._lastGPt.slice(); } } } }, HandleKeyUp: { value: function(event) { if(event.keyCode === Keyboard.ALT) { this._altKeyDown = false; } else if (event.keyCode === Keyboard.SHIFT) { this._shiftKeyDown = false; } } }, handleToolDoubleClick: { value: function () { var uc = this.application.ninja.currentDocument.documentRoot; //var uc = documentManagerModule.DocumentManager.activeDocument var ucMat = viewUtils.getMatrixFromElement(uc); var noTrans = ucMat.slice(); noTrans[12] = 0; noTrans[13] = 0; noTrans[14] = 0; var ucMatInv = glmat4.inverse( ucMat, [] ); var deltaMat = glmat4.multiply( noTrans, ucMatInv, [] ); this.application.ninja.stage.centerStage(); this.applyDeltaMat( deltaMat ); } }, handleMousewheel : { value:function(event) { var zoom = this.application.ninja.documentBar.zoomFactor/100.0; if (!zoom) zoom = 1.0; var delta = 0; if (event.wheelDelta) delta = 10*event.wheelDelta/120; //console.log( "delta: " + delta ); this.application.ninja.stage._iframeContainer.scrollLeft += delta; this.application.ninja.stage._scrollLeft += delta; delta *= zoom; var uc = this.application.ninja.currentDocument.documentRoot; var ucMat = viewUtils.getMatrixFromElement(uc); var offset = viewUtils.getElementOffset( uc ); //console.log( "uc offset: " + offset[0] ); var localToGlobalMat = viewUtils.getLocalToGlobalMatrix( uc ); var globalToLocalMat = glmat4.inverse( localToGlobalMat, []); var w = uc.offsetWidth, h = uc.offsetHeight; if(uc.width) w = uc.width; if(uc.height) h = uc.height; var localPt = [ w/2, h/2, 0]; var globalPt = MathUtils.transformAndDivideHomogeneousPoint( localPt, localToGlobalMat ); this.doMouseDown( { x:globalPt[0], y:globalPt[1] } ); globalPt[0] += delta; this._isDrawing = true; this.doMouseMove( { x:globalPt[0], y:globalPt[1] } ); this._isDrawing = false; } }, ///////////////////////////////////////////////////////////////////// // Simple tool API activate: { value: function() { //console.log( "PanTool.activate" ); } }, deactivate: { value: function() { //console.log( "PanTool.deactivate" ); } }, mouseDown: { value: function( event ) { //console.log( "PanTool.mouseDown" ); if (!this.application.ninja.currentDocument) return; var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); this.doMouseDown( point ); } }, doMouseDown: { value: function( point ) { //var tmpPt, tmpPt2, tmpPt3, tmpPt4, tmpMat, tmpMat2; // DEBUG. (see use of these points below) var hitRec = snapManager.snap( point.x, point.y, true ); if (hitRec) { //console.log( "hit: " + hitRec.getElement().id ); var globalPt = [point.x, point.y]; var elt = hitRec.getElement(); if (elt) { // get the userContent object (stage) and its matrix var userContent = this.application.ninja.currentDocument.documentRoot; var ucMat = viewUtils.getMatrixFromElement(userContent); var localToGlobalMat = viewUtils.getLocalToGlobalMatrix( elt ); var globalToLocalMat = glmat4.inverse( localToGlobalMat, []); if (elt != userContent) this._localPt = hitRec.calculateElementPreTransformScreenPoint(); else { var localPt = hitRec.calculateElementWorldPoint(); viewUtils.pushViewportObj( userContent ); var cop = viewUtils.getCenterOfProjection(); this._localPt = [cop[0] + localPt[0], cop[1] + localPt[1], localPt[2]]; viewUtils.popViewportObj(); } this._globalPt = MathUtils.transformAndDivideHomogeneousPoint( this._localPt, localToGlobalMat ); var tmpLocal = MathUtils.transformAndDivideHomogeneousPoint( this._globalPt, globalToLocalMat ); this._lastGPt = this._globalPt.slice(); this._shiftPt = this._lastGPt.slice(); this._lastY = this._lastGPt[1]; // set up the matrices we will be needing var eltToStageWorldMat = glmat4.multiply( ucMat, viewUtils.getObjToStageWorldMatrix(elt, true), []); this._worldPt = MathUtils.transformAndDivideHomogeneousPoint( this._localPt, eltToStageWorldMat ); // console.log( "screenPt: " + globalPt ); // console.log( "_worldPt: " + this._worldPt ); // console.log( "_localPt: " + this._localPt ); // console.log( "_globalPt: " + this._globalPt ); // console.log( "hit localPt: " + hitRec.calculateElementPreTransformScreenPoint() ); // get a matrix from user content world space to the screen viewUtils.pushViewportObj( userContent ); var cop = viewUtils.getCenterOfProjection(); var pDist = viewUtils.getPerspectiveDistFromElement(userContent); var projMat = glmat4.scale(Matrix.I(4), [pDist,pDist,pDist], []); projMat[11] = -1; projMat[15] = 1400; var v2s = Matrix.Translation([cop[0], cop[1], 0]); var ucWorldToGlobal = glmat4.multiply( v2s, projMat, [] ); var offset = viewUtils.getElementOffset( userContent ); var offMat = Matrix.Translation([offset[0], offset[1], 0]); glmat4.multiply( offMat, ucWorldToGlobal, ucWorldToGlobal ); this._globalToUCWorld = glmat4.inverse(ucWorldToGlobal, []); viewUtils.popViewportObj(); /* tmpPt = MathUtils.transformAndDivideHomogeneousPoint( this._globalPt, this._globalToUCWorld ); // DEBUG - tmpPt should equal this._worldPt tmpPt2 = MathUtils.transformAndDivideHomogeneousPoint( this._worldPt, ucWorldToGlobal ); // DEBUG - tmpPt2 should equal globalPt tmpPt3 = viewUtils.localToGlobal( this._localPt, elt ); tmpPt4 = MathUtils.transformAndDivideHomogeneousPoint( tmpPt3, this._globalToUCWorld ); tmpMat = glmat4.multiply(ucWorldToGlobal, eltToStageWorldMat, []); tmpMat2 = viewUtils.getLocalToGlobalMatrix( elt ); */ } } } }, mouseMove: { value: function( event ) { var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); this.doMouseMove( point ); } }, doMouseMove: { value: function( point ) { if (this._isDrawing) { // get the global screen point var gPt = [point.x, point.y, this._globalPt[2]]; if (this._altKeyDown) { var dy = 5*(point.y - this._lastY); this._globalPt[2] += dy; gPt = [this._lastGPt[0], this._lastGPt[1], this._globalPt[2]]; } else if (this._shiftKeyDown) { var dx = Math.abs( this._shiftPt[0] - gPt[0] ), dy = Math.abs( this._shiftPt[1] - gPt[1] ); if (dx >= dy) gPt[1] = this._shiftPt[1]; else gPt[0] = this._shiftPt[0]; } // update the scrollbars var deltaGPt = VecUtils.vecSubtract(2, gPt, this._lastGPt); this._lastGPt = gPt.slice(); this._lastY = point.y; var oldLeft = this.application.ninja.stage._iframeContainer.scrollLeft, oldTop = this.application.ninja.stage._iframeContainer.scrollTop; this.application.ninja.stage._iframeContainer.scrollLeft -= deltaGPt[0]; this.application.ninja.stage._iframeContainer.scrollTop -= deltaGPt[1]; deltaGPt[0] = oldLeft - this.application.ninja.stage._iframeContainer.scrollLeft; deltaGPt[1] = oldTop - this.application.ninja.stage._iframeContainer.scrollTop; gPt[0] -= deltaGPt[0]; gPt[1] -= deltaGPt[1]; this.updateGlobalToUCWorldMatrix(); var wPt = MathUtils.transformAndDivideHomogeneousPoint( gPt, this._globalToUCWorld ); var delta = vecUtils.vecSubtract( 3, wPt, this._worldPt ); if (!this._altKeyDown) delta[2] = 0; var transMat = Matrix.Translation( delta ); this._worldPt = wPt; // update everything this.applyDeltaMat( transMat ); } } }, mouseUp: { value: function( event ) { //console.log( "PanTool.mouseUp" ); this.application.ninja.stage.updatedStage = true; } }, applyDeltaMat: { value: function( transMat ) { // update the user content matrix var uc = this.application.ninja.currentDocument.documentRoot; var ucMat = viewUtils.getMatrixFromElement(uc); var newUCMat = glmat4.multiply( transMat, ucMat, [] ); viewUtils.setMatrixForElement( uc, newUCMat ); // redraw everything this.application.ninja.stage.updatedStage = true; } }, updateGlobalToUCWorldMatrix: { value: function() { // get the userContent object var userContent = this.application.ninja.currentDocument.documentRoot; // get a matrix from user content world space to the screen viewUtils.pushViewportObj( userContent ); var cop = viewUtils.getCenterOfProjection(); var pDist = viewUtils.getPerspectiveDistFromElement(userContent); var projMat = glmat4.scale(Matrix.I(4), [pDist,pDist,pDist], []); projMat[11] = -1; projMat[15] = 1400; var v2s = Matrix.Translation([cop[0], cop[1], 0]); var ucWorldToGlobal = glmat4.multiply( v2s, projMat, [] ); var offset = viewUtils.getElementOffset( userContent ); var offMat = Matrix.Translation([offset[0], offset[1], 0]); glmat4.multiply( offMat, ucWorldToGlobal, ucWorldToGlobal ); this._globalToUCWorld = glmat4.inverse(ucWorldToGlobal, []); viewUtils.popViewportObj(); } } } );