diff options
Diffstat (limited to 'js/tools')
-rwxr-xr-x | js/tools/PenTool.js | 849 |
1 files changed, 412 insertions, 437 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 5145eb39..06aac46c 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -18,8 +18,6 @@ var ViewUtils = require("js/helper-classes/3D/view-utils").ViewUtils; | |||
18 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; | 18 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; |
19 | var SubPath = require("js/lib/geom/sub-path").SubPath; | 19 | var SubPath = require("js/lib/geom/sub-path").SubPath; |
20 | 20 | ||
21 | //todo remove this global var | ||
22 | var g_DoPenToolMouseMove = true; | ||
23 | 21 | ||
24 | exports.PenTool = Montage.create(ShapeTool, { | 22 | exports.PenTool = Montage.create(ShapeTool, { |
25 | 23 | ||
@@ -35,14 +33,11 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
35 | _parentNode: { enumerable: false, value: null, writable: true }, | 33 | _parentNode: { enumerable: false, value: null, writable: true }, |
36 | _toolsPropertiesContainer: { enumerable: false, value: null, writable: true }, | 34 | _toolsPropertiesContainer: { enumerable: false, value: null, writable: true }, |
37 | 35 | ||
38 | // Need to keep track of current mouse position for KEY modifiers event which do not have mouse coordinates | 36 | //set this to true if you want to keep making subpaths after closing current subpath (debugging only) |
39 | _currentX: { value: 0, writable: true }, | 37 | _makeMultipleSubpaths: { value: true, writable: true }, |
40 | _currentY: { value: 0, writable: true }, | ||
41 | |||
42 | //the subpaths are what is displayed on the screen currently, with _selectedSubpath being the active one currently being edited | ||
43 | _selectedSubpath: { value: null, writable: true }, | ||
44 | _makeMultipleSubpaths: { value: true, writable: true }, //set this to true if you want to keep making subpaths after closing current subpath | ||
45 | 38 | ||
39 | //set this to false if you don't want the mouse move handler being called when the mouse is not down (debugging only) | ||
40 | _trackMouseMoveWhenUp: {value: true, writable: false}, | ||
46 | 41 | ||
47 | //whether the user has held down the Alt key | 42 | //whether the user has held down the Alt key |
48 | _isAltDown: { value: false, writable: true }, | 43 | _isAltDown: { value: false, writable: true }, |
@@ -50,7 +45,8 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
50 | //whether the user has held down the Esc key | 45 | //whether the user has held down the Esc key |
51 | _isEscapeDown: {value: false, writable: true }, | 46 | _isEscapeDown: {value: false, writable: true }, |
52 | 47 | ||
53 | //whether we have just started a new path (set true in mousedown, and set false in mouse up | 48 | //whether we have just started a new path (may set true in mousedown, and always set false in mouse up |
49 | //todo this seems to be unnecessary | ||
54 | _isNewPath: {value: false, writable: true}, | 50 | _isNewPath: {value: false, writable: true}, |
55 | 51 | ||
56 | //whether we have clicked one of the endpoints after entering the pen tool in ENTRY_SELECT_PATH edit mode | 52 | //whether we have clicked one of the endpoints after entering the pen tool in ENTRY_SELECT_PATH edit mode |
@@ -59,22 +55,26 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
59 | //when the user wants to place a selected anchor point on top of another point, this is the target where the point will be placed | 55 | //when the user wants to place a selected anchor point on top of another point, this is the target where the point will be placed |
60 | _snapTargetIndex: { value: -1, writable: true }, | 56 | _snapTargetIndex: { value: -1, writable: true }, |
61 | 57 | ||
62 | //whether or not we're using webgl for drawing | 58 | //index of the anchor point that the user has hovered over |
63 | _useWebGL: {value: false, writable: false }, | 59 | _hoveredAnchorIndex: {value: -1, writable: true}, |
64 | 60 | ||
65 | //the canvas created by the pen tool...this is grown or shrunk with the path (if the canvas was not already provided) | 61 | //whether or not we're using webgl for drawing (set to false until we have webgl-ready stroke and fill regions) |
66 | _penCanvas: { value: null, writable: true }, | 62 | _useWebGL: {value: false, writable: false }, |
67 | 63 | ||
68 | //the plane matrix for the first click...so the entire path is on the same plane | 64 | //the _selectedSubpath is the active subpath currently being edited |
69 | _penPlaneMat: { value: null, writable: true }, | 65 | _selectedSubpath: { value: null, writable: true }, |
70 | 66 | ||
71 | //the plane equation (in stage world space) for the current path being drawn | 67 | //the canvas for the selected subpath...this is grown or shrunk by the pen tool with the subpath (if the canvas was not already provided) |
72 | _dragPlane: {value: null, writable: true}, | 68 | _selectedSubpathCanvas: { value: null, writable: true }, |
73 | 69 | ||
74 | //index of the anchor point that the user has hovered over | 70 | //the plane matrix for the first click...so the entire path is on the same plane |
75 | _hoveredAnchorIndex: {value: -1, writable: true}, | 71 | // todo this might be unnecessary as we can get this from element mediator (but that may be slow) |
72 | _selectedSubpathPlaneMat: { value: null, writable: true }, | ||
76 | 73 | ||
77 | //constants used for picking points --- NOTE: these should be user-settable parameters | 74 | //the center of the subpath center in stageworld space |
75 | _selectedSubpathCanvasCenter: {value: null, writable: true}, | ||
76 | |||
77 | //constants used for picking points --- todo: these should be user-settable parameters | ||
78 | _PICK_POINT_RADIUS: { value: 4, writable: false }, | 78 | _PICK_POINT_RADIUS: { value: 4, writable: false }, |
79 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, | 79 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, |
80 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, | 80 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, |
@@ -89,58 +89,46 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
89 | EDIT_PREV_NEXT: { value: 8, writable: false }, | 89 | EDIT_PREV_NEXT: { value: 8, writable: false }, |
90 | _editMode: { value: this.EDIT_NONE, writable: true }, | 90 | _editMode: { value: this.EDIT_NONE, writable: true }, |
91 | 91 | ||
92 | //constants used for selection modes on entry to pen tool (mutually exclusive) | 92 | //constants used for selection modes on entry to pen tool (mutually exclusive i.e. cannot be OR-ed) |
93 | ENTRY_SELECT_NONE: { value: 0, writable: false}, | 93 | ENTRY_SELECT_NONE: { value: 0, writable: false}, |
94 | ENTRY_SELECT_CANVAS: { value: 1, writable: false}, | 94 | ENTRY_SELECT_CANVAS: { value: 1, writable: false}, |
95 | ENTRY_SELECT_PATH: { value: 2, writable: false}, | 95 | ENTRY_SELECT_PATH: { value: 2, writable: false}, |
96 | _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true}, | 96 | _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true}, |
97 | 97 | ||
98 | 98 | ||
99 | 99 | // get the stage world position corresponding to the (x,y) mouse event position by querying the snap manager | |
100 | _getUnsnappedPosition: { | 100 | // but temporarily turning off all snapping |
101 | value: function(x,y){ | 101 | _getMouseEventPosition : { |
102 | value: function(x,y, getStageWorld, doSnap){ | ||
102 | var elemSnap = snapManager.elementSnapEnabled(); | 103 | var elemSnap = snapManager.elementSnapEnabled(); |
103 | var gridSnap = snapManager.gridSnapEnabled(); | 104 | var gridSnap = snapManager.gridSnapEnabled(); |
104 | var alignSnap = snapManager.snapAlignEnabled(); | 105 | var alignSnap = snapManager.snapAlignEnabled(); |
105 | 106 | ||
106 | snapManager.enableElementSnap(false); | 107 | if (!doSnap){ |
107 | snapManager.enableGridSnap(false); | 108 | snapManager.enableElementSnap(false); |
108 | snapManager.enableSnapAlign(false); | 109 | snapManager.enableGridSnap(false); |
110 | snapManager.enableSnapAlign(false); | ||
111 | } | ||
109 | 112 | ||
110 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); | 113 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); |
111 | var unsnappedpos = //snapManager.snap(point.x, point.y, false).calculateStageWorldPoint(); | 114 | var pos; |
112 | DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); | 115 | if (getStageWorld){ |
113 | this._dragPlane = snapManager.getDragPlane(); | 116 | pos = (snapManager.snap(point.x, point.y, false)).calculateStageWorldPoint(); |
117 | } else { | ||
118 | pos = (snapManager.snap(point.x, point.y, false)).getScreenPoint(); | ||
119 | } | ||
120 | var dragPlane = snapManager.getDragPlane(); | ||
114 | 121 | ||
115 | snapManager.enableElementSnap(elemSnap); | 122 | if (!doSnap){ |
116 | snapManager.enableGridSnap(gridSnap); | 123 | snapManager.enableElementSnap(elemSnap); |
117 | snapManager.enableSnapAlign(alignSnap); | 124 | snapManager.enableGridSnap(gridSnap); |
125 | snapManager.enableSnapAlign(alignSnap); | ||
126 | } | ||
118 | 127 | ||
119 | return unsnappedpos; | 128 | return [pos, dragPlane]; |
120 | } | 129 | } |
121 | }, | 130 | }, |
122 | 131 | ||
123 | _getUnsnappedScreenPosition: { | ||
124 | value: function(x,y){ | ||
125 | var elemSnap = snapManager.elementSnapEnabled(); | ||
126 | var gridSnap = snapManager.gridSnapEnabled(); | ||
127 | var alignSnap = snapManager.snapAlignEnabled(); | ||
128 | |||
129 | snapManager.enableElementSnap(false); | ||
130 | snapManager.enableGridSnap(false); | ||
131 | snapManager.enableSnapAlign(false); | ||
132 | |||
133 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); | ||
134 | var unsnappedpos = (snapManager.snap(point.x, point.y, false)).getScreenPoint(); | ||
135 | this._dragPlane = snapManager.getDragPlane(); | ||
136 | |||
137 | snapManager.enableElementSnap(elemSnap); | ||
138 | snapManager.enableGridSnap(gridSnap); | ||
139 | snapManager.enableSnapAlign(alignSnap); | ||
140 | |||
141 | return unsnappedpos; | ||
142 | } | ||
143 | }, | ||
144 | ShowToolProperties: { | 132 | ShowToolProperties: { |
145 | value: function () { | 133 | value: function () { |
146 | this._penView = PenView.create(); | 134 | this._penView = PenView.create(); |
@@ -152,6 +140,43 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
152 | 140 | ||
153 | }, | 141 | }, |
154 | 142 | ||
143 | //use the snap manager to build a hit record corresponding to the screen X, Y position | ||
144 | // will use the plane of the selected path as the working plane if available, else use stage | ||
145 | getHitRecord:{ | ||
146 | value: function(x,y){ | ||
147 | var drawingCanvas = ViewUtils.getStageElement(); | ||
148 | if (this._selectedSubpathCanvas){ | ||
149 | drawingCanvas = this._selectedSubpathCanvas; | ||
150 | } | ||
151 | var contentPlane = ViewUtils.getUnprojectedElementPlane(drawingCanvas); | ||
152 | snapManager.pushWorkingPlane(contentPlane); | ||
153 | var tmpPoint = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); | ||
154 | var hitRec = snapManager.snap(tmpPoint.x, tmpPoint.y, false); | ||
155 | snapManager.popWorkingPlane(); | ||
156 | return hitRec; | ||
157 | } | ||
158 | }, | ||
159 | |||
160 | // ********************************************************************************************************** | ||
161 | // Mouse down handler | ||
162 | // IF the selected subpath is null, it means we're going to start a new subpath | ||
163 | // Create a new subpath | ||
164 | // Compute the mouse position in stage world space (lying on stage or selected subpath canvas) | ||
165 | // IF selected subpath does not have a canvas yet, | ||
166 | // IF this is the first anchor point of the selected subpath | ||
167 | // Store the plane mat and drag plane of this hit record (will be used for creating a canvas) | ||
168 | // Add the mouse position (in stage world space) as an anchor point | ||
169 | // ELSE (we may add to the selected subpath) | ||
170 | // Compute the mouse position in local (selected subpath canvas) space | ||
171 | // IF we hit the path: | ||
172 | // Either select an anchor or insert an anchor and select it | ||
173 | // (also set proper flags when select endpoint of open path in ENTRY_SELECT_PATH mode) | ||
174 | // ELSE | ||
175 | // If selected subpath is closed (and we're not in ENTRY_SELECT_PATH mode) | ||
176 | // Create a new subpath | ||
177 | // Add the mouse position (in selected subpath's local space) as an anchor point (call global to local) | ||
178 | // Draw the selected subpath anchors and the selected subpath itself in the stage's context | ||
179 | // ********************************************************************************************************** | ||
155 | HandleLeftButtonDown: | 180 | HandleLeftButtonDown: |
156 | { | 181 | { |
157 | value: function (event) { | 182 | value: function (event) { |
@@ -160,118 +185,145 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
160 | //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) | 185 | //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) |
161 | return; | 186 | return; |
162 | } | 187 | } |
188 | |||
189 | //set the drawing flags (see the drawing-tool.js base class) | ||
163 |