/* <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 ShapeTool = require("js/tools/ShapeTool").ShapeTool; var ShapesController = require("js/controllers/elements/shapes-controller").ShapesController; var DrawingToolBase = require("js/tools/drawing-tool-base").DrawingToolBase; var defaultEventManager = require("montage/core/event/event-manager").defaultEventManager; var Montage = require("montage/core/core").Montage; var NJUtils = require("js/lib/NJUtils").NJUtils; var ElementMediator = require("js/mediators/element-mediator").ElementMediator; var TagTool = require("js/tools/TagTool").TagTool; var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; var BrushStroke = require("js/lib/geom/brush-stroke").BrushStroke; exports.BrushTool = Montage.create(ShapeTool, { hasReel: { value: false }, _toolID: { value: "brushTool" }, _imageID: { value: "brushToolImg" }, _toolImageClass: { value: "brushToolUp" }, _selectedToolImageClass: { value: "brushToolDown" }, _toolTipText: { value: "Brush Tool" }, _brushView: { value: null, writable: true }, _selectedToolClass: { value: "brushToolSpecificProperties" }, _penToolProperties: { enumerable: false, value: null, writable: true }, _parentNode: { enumerable: false, value: null, writable: true }, _toolsPropertiesContainer: { enumerable: false, value: null, writable: true }, //config options _useWebGL: {value: false, writable: false}, //view options _brushStrokeCanvas: {value: null, writable: true}, _brushStrokePlaneMat: {value: null, writable: true}, //the current brush stroke _selectedBrushStroke: {value: null, writable: true}, ShowToolProperties: { value: function () { this._brushView = PenView.create(); this._brushView.element = document.getElementById('topPanelContainer').children[0]; this._brushView.needsDraw = true; this._brushView.addEventListener(ToolEvents.TOOL_OPTION_CHANGE, this, false); } }, HandleLeftButtonDown: { value: function (event) { //ignore any right or middle clicks if (event.button !== 0) { //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) return; } if (this._canDraw) { this._isDrawing = true; } this.startDraw(event); if (this._brushStrokePlaneMat === null) { this._brushStrokePlaneMat = this.mouseDownHitRec.getPlaneMatrix(); } //start a new brush stroke if (this._selectedBrushStroke === null){ this._selectedBrushStroke = new BrushStroke(); if (this.application.ninja.colorController.colorToolbar.stroke.webGlColor){ this._selectedBrushStroke.setStrokeColor(this.application.ninja.colorController.colorToolbar.stroke.webGlColor); } if (this.application.ninja.colorController.colorToolbar.fill.webGlColor){ this._selectedBrushStroke.setSecondStrokeColor(this.application.ninja.colorController.colorToolbar.fill.webGlColor); } //add this point to the brush stroke in case the user does a mouse up before doing a mouse move var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); this._selectedBrushStroke.addPoint(currMousePos); var strokeSize = 1; if (this.options.strokeSize) { strokeSize = ShapesController.GetValueInPixels(this.options.strokeSize.value, this.options.strokeSize.units); } this._selectedBrushStroke.setStrokeWidth(strokeSize); var strokeHardness = 100; if (this.options.strokeHardness){ strokeHardness = ShapesController.GetValueInPixels(this.options.strokeHardness.value, this.options.strokeHardness.units); } this._selectedBrushStroke.setStrokeHardness(strokeHardness); var doSmoothing = false; if (this.options.doSmoothing){ doSmoothing = this.options.doSmoothing; } this._selectedBrushStroke.setDoSmoothing(doSmoothing); var useCalligraphic = false; if (this.options.useCalligraphic){ useCalligraphic = this.options.useCalligraphic; } if (useCalligraphic) { this._selectedBrushStroke.setStrokeUseCalligraphic(true); var strokeAngle = 0; if (this.options.strokeAngle){ strokeAngle= ShapesController.GetValueInPixels(this.options.strokeAngle.value, this.options.strokeAngle.units); } this._selectedBrushStroke.setStrokeAngle(Math.PI * -strokeAngle/180); } else { this._selectedBrushStroke.setStrokeUseCalligraphic(false); } } NJevent("enableStageMove");//stageManagerModule.stageManager.enableMouseMove(); } //value: function (event) { }, //HandleLeftButtonDown _getUnsnappedPosition: { value: function(x,y){ var elemSnap = snapManager.elementSnapEnabled(); var gridSnap = snapManager.gridSnapEnabled(); var alignSnap = snapManager.snapAlignEnabled(); snapManager.enableElementSnap(false); snapManager.enableGridSnap(false); snapManager.enableSnapAlign(false); var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); snapManager.enableElementSnap(elemSnap); snapManager.enableGridSnap(gridSnap); snapManager.enableSnapAlign(alignSnap); return unsnappedpos; } }, //need to override this function because the ShapeTool's definition contains a clearDrawingCanvas call - Pushkar // might not need to override once we draw using OpenGL instead of SVG // Also took out all the snapping code for now...need to add that back HandleMouseMove: { value: function (event) { //ignore any right or middle clicks if (event.button !== 0) { //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) return; } if (this._isDrawing) { var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); if (this._selectedBrushStroke && this._selectedBrushStroke.getNumPoints()<1000){ this._selectedBrushStroke.addPoint(currMousePos); } this.ShowCurrentBrushStrokeOnStage(); } //if (this._isDrawing) { //this.drawLastSnap(); //TODO.. is this line necessary if we're not snapping? // Required cleanup for both Draw/Feedbacks }//value: function(event) }, HandleLeftButtonUp: { value: function (event) { /*var drawData = this.getDrawingData(); if (drawData) { if (this._brushStrokePlaneMat === null) { this._brushStrokePlaneMat = drawData.planeMat; } } if (this._isDrawing) { this.doDraw(event); }*/ this.endDraw(event); this._isDrawing = false; this._hasDraw = false; //display the previously drawn stroke in a separate canvas this.RenderCurrentBrushStroke(); this._selectedBrushStroke = null; this._brushStrokeCanvas = null; NJevent("disableStageMove"); } }, ShowCurrentBrushStrokeOnStage:{ value: function() { //clear the canvas before we draw anything else this.application.ninja.stage.clearDrawingCanvas(); if (this._selectedBrushStroke && this._selectedBrushStroke.getNumPoints()>0){ //this._selectedBrushStroke.computeMetaGeometry(); var ctx = this.application.ninja.stage.drawingContext;//stageManagerModule.stageManager.drawingContext; if (ctx === null) throw ("null drawing context in Brushtool::ShowCurrentBrushStrokeOnStage"); ctx.save(); var horizontalOffset = this.application.ninja.stage.userContentLeft; var verticalOffset = this.application.ninja.stage.userContentTop; var numPoints = this._selectedBrushStroke.getNumPoints(); ctx.lineWidth = 1; ctx.strokeStyle = "black"; ctx.beginPath(); var pt = this._selectedBrushStroke.getPoint(0); ctx.moveTo(pt[0]+ horizontalOffset,pt[1]+ verticalOffset); for (var i = 1; i < numPoints; i++) { pt = this._selectedBrushStroke.getPoint(i); var x = pt[0]+ horizontalOffset; var y = pt[1]+ verticalOffset; ctx.lineTo(x,y); } ctx.stroke(); ctx.restore(); } } }, RenderCurrentBrushStroke:{ value: function() { if (this._selectedBrushStroke){ this._selectedBrushStroke.computeMetaGeometry(); var bboxMin = this._selectedBrushStroke.getBBoxMin(); var bboxMax = this._selectedBrushStroke.getBBoxMax(); var bboxWidth = bboxMax[0] - bboxMin[0]; var bboxHeight = bboxMax[1] - bboxMin[1]; var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; this._selectedBrushStroke.setCanvasX(bboxMid[0]); this._selectedBrushStroke.setCanvasY(bboxMid[1]); //call render shape with the bbox width and height this.RenderShape(bboxWidth, bboxHeight, this._brushStrokePlaneMat, bboxMid, this._brushStrokeCanvas); } } }, RenderShape: { value: function (w, h, planeMat, midPt, canvas) { if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { return; } var left = Math.round(midPt[0] - 0.5 * w); var top = Math.round(midPt[1] - 0.5 * h); if (!canvas) { var newCanvas = NJUtils.makeNJElement("canvas", "Brushstroke", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); var elementModel = TagTool.makeElement(w, h, planeMat, midPt, newCanvas); ElementMediator.addElement(newCanvas, elementModel.data, true); // create all the GL stuff var world = this.getGLWorld(newCanvas, this._useWebGL); //store a reference to this newly created canvas this._brushStrokeCanvas = newCanvas; var brushStroke = this._selectedBrushStroke; if (brushStroke){ brushStroke.setWorld(world); brushStroke.setPlaneMatrix(planeMat); var planeMatInv = glmat4.inverse( planeMat, [] ); brushStroke.setPlaneMatrixInverse(planeMatInv); brushStroke.setPlaneCenter(midPt); world.addObject(brushStroke); world.render(); //TODO this will not work if there are multiple shapes in the same canvas newCanvas.elementModel.shapeModel.GLGeomObj = brushStroke; } } //if (!canvas) { else { var world = null; if (canvas.elementModel.shapeModel && canvas.elementModel.shapeModel.GLWorld) { world = canvas.elementModel.shapeModel.GLWorld; } else { world = this.getGLWorld(canvas, this._useWebGL); } if (this._entryEditMode !== this.ENTRY_SELECT_CANVAS){ //update the left and top of the canvas element var canvasArray=[canvas]; ElementMediator.setProperty(canvasArray, "left", [parseInt(left)+"px"],"Changing", "brushTool"); ElementMediator.setProperty(canvasArray, "top", [parseInt(top) + "px"],"Changing", "brushTool"); canvas.width = w; canvas.height = h; //update the viewport and projection to reflect the new canvas width and height world.setViewportFromCanvas(canvas); if (this._useWebGL){ var cam = world.renderer.cameraManager().getActiveCamera(); cam.setPerspective(world.getFOV(), world.getAspect(), world.getZNear(), world.getZFar()); } } var brushStroke = this._selectedBrushStroke; if (brushStroke){ brushStroke.setDrawingTool(this); brushStroke.setPlaneMatrix(planeMat); var planeMatInv = glmat4.inverse( planeMat, [] ); brushStroke.setPlaneMatrixInverse(planeMatInv); brushStroke.setPlaneCenter(midPt); brushStroke.setWorld(world); world.addIfNewObject(brushStroke); //world.addObject(subpath); world.render(); //TODO this will not work if there are multiple shapes in the same canvas canvas.elementModel.shapeModel.GLGeomObj = brushStroke; } } //else of if (!canvas) { } //value: function (w, h, planeMat, midPt, canvas) { }, //RenderShape: { Configure: { value: function (wasSelected) { if (wasSelected) { console.log("Entered BrushTool"); } else { console.log("Left BrushTool"); } } } });