1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "VertexTool.h"
21 
22 #include "SetAny.h"
23 #include "Model/Brush.h"
24 #include "Model/BrushGeometry.h"
25 #include "Model/HitAdapter.h"
26 #include "Model/NodeVisitor.h"
27 #include "Model/Object.h"
28 #include "Renderer/RenderContext.h"
29 #include "View/InputState.h"
30 #include "View/Grid.h"
31 #include "View/Lasso.h"
32 #include "View/MapDocument.h"
33 #include "View/MoveBrushEdgesCommand.h"
34 #include "View/MoveBrushFacesCommand.h"
35 #include "View/MoveBrushVerticesCommand.h"
36 #include "View/Selection.h"
37 #include "View/SnapBrushVerticesCommand.h"
38 #include "View/SplitBrushEdgesCommand.h"
39 #include "View/SplitBrushFacesCommand.h"
40 #include "View/VertexCommand.h"
41 
42 #include <cassert>
43 
44 namespace TrenchBroom {
45     namespace View {
VertexTool(MapDocumentWPtr document)46         VertexTool::VertexTool(MapDocumentWPtr document) :
47         Tool(false),
48         m_document(document),
49         m_handleManager(m_document),
50         m_mode(Mode_Move),
51         m_changeCount(0),
52         m_ignoreChangeNotifications(false),
53         m_dragging(false) {}
54 
grid() const55         const Grid& VertexTool::grid() const {
56             return lock(m_document)->grid();
57         }
58 
pick(const Ray3 & pickRay,const Renderer::Camera & camera,Model::PickResult & pickResult)59         void VertexTool::pick(const Ray3& pickRay, const Renderer::Camera& camera, Model::PickResult& pickResult) {
60             m_handleManager.pick(pickRay, camera, pickResult, m_mode == Mode_Split);
61         }
62 
deselectAll()63         bool VertexTool::deselectAll() {
64             if (m_handleManager.selectedVertexHandles().empty() &&
65                 m_handleManager.selectedEdgeHandles().empty() &&
66                 m_handleManager.selectedFaceHandles().empty())
67                 return false;
68 
69             m_handleManager.deselectAllHandles();
70             m_mode = Mode_Move;
71             refreshViews();
72             return true;
73         }
74 
mergeVertices(const Model::Hit & hit)75         bool VertexTool::mergeVertices(const Model::Hit& hit) {
76             if (m_handleManager.selectedVertexCount() != 1)
77                 return false;
78             if (hit.type() != VertexHandleManager::VertexHandleHit)
79                 return false;
80             const Vec3 targetPosition = hit.target<Vec3>();
81             const Vec3 originalPosition = m_handleManager.selectedVertexHandlePositions().front();
82             const Vec3 delta = targetPosition - originalPosition;
83             moveVerticesAndRebuildBrushGeometry(delta);
84             return true;
85         }
86 
handleDoubleClicked(const Model::Hit & hit)87         bool VertexTool::handleDoubleClicked(const Model::Hit& hit) {
88             if (hit.type() == VertexHandleManager::EdgeHandleHit) {
89                 m_handleManager.deselectAllHandles();
90                 m_handleManager.selectEdgeHandle(hit.target<Vec3>());
91                 m_mode = Mode_Split;
92             } else {
93                 m_handleManager.deselectAllHandles();
94                 m_handleManager.selectFaceHandle(hit.target<Vec3>());
95                 m_mode = Mode_Split;
96             }
97             refreshViews();
98             return true;
99         }
100 
select(const Model::Hit::List & hits,const bool addToSelection)101         bool VertexTool::select(const Model::Hit::List& hits, const bool addToSelection) {
102             assert(!hits.empty());
103             const Model::Hit& hit = hits.front();
104             if (hit.type() == VertexHandleManager::VertexHandleHit)
105                 selectVertex(hits, addToSelection);
106             else if (hit.type() == VertexHandleManager::EdgeHandleHit)
107                 selectEdge(hits, addToSelection);
108             else
109                 selectFace(hits, addToSelection);
110             refreshViews();
111             return true;
112         }
113 
select(const Lasso & lasso,const bool modifySelection)114         void VertexTool::select(const Lasso& lasso, const bool modifySelection) {
115             if (m_handleManager.selectedEdgeCount() > 0) {
116                 const Vec3::List contained = lasso.containedPoints(m_handleManager.edgeHandlePositions());
117                 if (!modifySelection) m_handleManager.deselectAllEdgeHandles();
118                 m_handleManager.toggleEdgeHandles(contained);
119             } else if (m_handleManager.selectedFaceCount() > 0) {
120                 const Vec3::List contained = lasso.containedPoints(m_handleManager.faceHandlePositions());
121                 if (!modifySelection) m_handleManager.deselectAllFaceHandles();
122                 m_handleManager.toggleFaceHandles(contained);
123             } else {
124                 const Vec3::List contained = lasso.containedPoints(m_handleManager.vertexHandlePositions());
125                 if (!modifySelection) m_handleManager.deselectAllVertexHandles();
126                 m_handleManager.toggleVertexHandles(contained);
127             }
128             refreshViews();
129         }
130 
beginMove(const Model::Hit & hit)131         bool VertexTool::beginMove(const Model::Hit& hit) {
132             assert(hit.isMatch());
133 
134             const Vec3 handlePosition = hit.target<Vec3>();
135             if (!m_handleManager.isHandleSelected(handlePosition)) {
136                 m_handleManager.deselectAllHandles();
137                 if (hit.type() == VertexHandleManager::VertexHandleHit)
138                     m_handleManager.selectVertexHandle(handlePosition);
139                 else if (hit.type() == VertexHandleManager::EdgeHandleHit)
140                     m_handleManager.selectEdgeHandle(handlePosition);
141                 else
142                     m_handleManager.selectFaceHandle(handlePosition);
143                 refreshViews();
144             }
145 
146             MapDocumentSPtr document = lock(m_document);
147             document->beginTransaction(actionName());
148 
149             m_dragHandlePosition = handlePosition;
150             m_dragging = true;
151             return true;
152         }
153 
move(const Vec3 & delta)154         VertexTool::MoveResult VertexTool::move(const Vec3& delta) {
155             return moveVertices(delta);
156         }
157 
endMove()158         void VertexTool::endMove() {
159             MapDocumentSPtr document = lock(m_document);
160             document->commitTransaction();
161             rebuildBrushGeometry();
162             m_mode = Mode_Move;
163             m_dragging = false;
164         }
165 
cancelMove()166         void VertexTool::cancelMove() {
167             MapDocumentSPtr document = lock(m_document);
168             document->cancelTransaction();
169             m_mode = Mode_Move;
170             m_dragging = false;
171         }
172 
renderHandles(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch)173         void VertexTool::renderHandles(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch) {
174             m_handleManager.render(renderContext, renderBatch, m_mode == Mode_Split);
175         }
176 
renderHighlight(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch)177         void VertexTool::renderHighlight(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch) {
178             renderHighlight(renderContext, renderBatch, m_dragHandlePosition);
179         }
180 
renderHighlight(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch,const Vec3 & position)181         void VertexTool::renderHighlight(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& position) {
182             m_handleManager.renderHighlight(renderContext, renderBatch, position);
183         }
184 
renderEdgeHighlight(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch,const Vec3 & handlePosition)185         void VertexTool::renderEdgeHighlight(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& handlePosition) {
186             m_handleManager.renderEdgeHighlight(renderContext, renderBatch, handlePosition);
187         }
188 
renderFaceHighlight(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch,const Vec3 & handlePosition)189         void VertexTool::renderFaceHighlight(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& handlePosition) {
190             m_handleManager.renderFaceHighlight(renderContext, renderBatch, handlePosition);
191         }
192 
renderGuide(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch)193         void VertexTool::renderGuide(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch) {
194             renderGuide(renderContext, renderBatch, m_dragHandlePosition);
195         }
196 
renderGuide(Renderer::RenderContext & renderContext,Renderer::RenderBatch & renderBatch,const Vec3 & position)197         void VertexTool::renderGuide(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& position) {
198             m_handleManager.renderGuide(renderContext, renderBatch, position);
199         }
200 
cancel()201         bool VertexTool::cancel() {
202             if (m_handleManager.hasSelectedHandles()) {
203                 m_handleManager.deselectAllHandles();
204                 return true;
205             }
206             return false;
207         }
208 
handleBrushes(const Vec3 & position,Model::BrushSet & brushes) const209         bool VertexTool::handleBrushes(const Vec3& position, Model::BrushSet& brushes) const {
210             bool newBrush = true;
211             const Model::BrushSet& handleBrushes = m_handleManager.brushes(position);
212             Model::BrushSet::const_iterator bIt, bEnd;
213             for (bIt = handleBrushes.begin(), bEnd = handleBrushes.end(); bIt != bEnd; ++bIt) {
214                 Model::Brush* brush = *bIt;
215                 newBrush &= brushes.insert(brush).second;
216             }
217             return newBrush;
218         }
219 
handleSelected(const Vec3 & position) const220         bool VertexTool::handleSelected(const Vec3& position) const {
221             return m_handleManager.isEdgeHandleSelected(position);
222         }
223 
hasSelectedHandles() const224         bool VertexTool::hasSelectedHandles() const {
225             return (m_handleManager.selectedVertexCount() > 0 ||
226                     m_handleManager.selectedEdgeCount() > 0 ||
227                     m_handleManager.selectedFaceCount() > 0);
228         }
229 
moveVerticesAndRebuildBrushGeometry(const Vec3 & delta)230         void VertexTool::moveVerticesAndRebuildBrushGeometry(const Vec3& delta) {
231             if (hasSelectedHandles()) {
232                 moveVertices(delta);
233                 rebuildBrushGeometry();
234                 m_mode = Mode_Move;
235             }
236         }
237 
canSnapVertices() const238         bool VertexTool::canSnapVertices() const {
239             if (m_handleManager.selectedEdgeCount() > 0 ||
240                 m_handleManager.selectedFaceCount() > 0)
241                 return false;
242             MapDocumentSPtr document = lock(m_document);
243             return m_handleManager.selectedVertexCount() > 0 || document->selectedNodes().hasOnlyBrushes();
244         }
245 
snapVertices(const size_t snapTo)246         void VertexTool::snapVertices(const size_t snapTo) {
247             assert(canSnapVertices());
248             MapDocumentSPtr document = lock(m_document);
249             document->snapVertices(m_handleManager.selectedVertexHandles(), snapTo);
250         }
251 
selectVertex(const Model::Hit::List & hits,const bool addToSelection)252         void VertexTool::selectVertex(const Model::Hit::List& hits, const bool addToSelection) {
253             m_handleManager.deselectAllEdgeHandles();
254             m_handleManager.deselectAllFaceHandles();
255 
256             size_t selected = 0;
257             Model::Hit::List::const_iterator it, end;
258             for (it = hits.begin(), end = hits.end(); it != end; ++it) {
259                 const Model::Hit& hit = *it;
260                 const Vec3 position = hit.target<Vec3>();
261                 if (m_handleManager.isVertexHandleSelected(position))
262                     ++selected;
263             }
264 
265             if (selected < hits.size()) {
266                 if (!addToSelection)
267                     m_handleManager.deselectAllHandles();
268                 for (it = hits.begin(), end = hits.end(); it != end; ++it) {
269                     const Model::Hit& hit = *it;
270                     const Vec3 position = hit.target<Vec3>();
271                     m_handleManager.selectVertexHandle(position);
272                 }
273             } else {
274                 if (addToSelection) {
275                     for (it = hits.begin(), end = hits.end(); it != end; ++it) {
276                         const Model::Hit& hit = *it;
277                         const Vec3 position = hit.target<Vec3>();
278                         m_handleManager.deselectVertexHandle(position);
279                     }
280                 }
281             }
282         }
283 
selectEdge(const Model::Hit::List & hits,const bool addToSelection)284         void VertexTool::selectEdge(const Model::Hit::List& hits, const bool addToSelection) {
285             m_handleManager.deselectAllVertexHandles();
286             m_handleManager.deselectAllFaceHandles();
287 
288             size_t selected = 0;
289             Model::Hit::List::const_iterator it, end;
290             for (it = hits.begin(), end = hits.end(); it != end; ++it) {
291                 const Model::Hit& hit = *it;
292                 const Vec3 position = hit.target<Vec3>();
293                 if (m_handleManager.isEdgeHandleSelected(position))
294                     ++selected;
295             }
296 
297             if (selected < hits.size()) {
298                 if (!addToSelection)
299                     m_handleManager.deselectAllHandles();
300                 for (it = hits.begin(), end = hits.end(); it != end; ++it) {
301                     const Model::Hit& hit = *it;
302                     const Vec3 position = hit.target<Vec3>();
303                     m_handleManager.selectEdgeHandle(position);
304                 }
305             } else {
306                 if (addToSelection) {
307                     for (it = hits.begin(), end = hits.end(); it != end; ++it) {
308                         const Model::Hit& hit = *it;
309                         const Vec3 position = hit.target<Vec3>();
310                         m_handleManager.deselectEdgeHandle(position);
311                     }
312                 }
313             }
314         }
315 
selectFace(const Model::Hit::List & hits,const bool addToSelection)316         void VertexTool::selectFace(const Model::Hit::List& hits, const bool addToSelection) {
317             m_handleManager.deselectAllVertexHandles();
318             m_handleManager.deselectAllEdgeHandles();
319 
320             size_t selected = 0;
321             Model::Hit::List::const_iterator it, end;
322             for (it = hits.begin(), end = hits.end(); it != end; ++it) {
323                 const Model::Hit& hit = *it;
324                 const Vec3 position = hit.target<Vec3>();
325                 if (m_handleManager.isFaceHandleSelected(position))
326                     selected++;
327             }
328 
329             if (selected < hits.size()) {
330                 if (!addToSelection)
331                     m_handleManager.deselectAllHandles();
332                 for (it = hits.begin(), end = hits.end(); it != end; ++it) {
333                     const Model::Hit& hit = *it;
334                     const Vec3 position = hit.target<Vec3>();
335                     m_handleManager.selectFaceHandle(position);
336                 }
337             } else {
338                 if (addToSelection) {
339                     for (it = hits.begin(), end = hits.end(); it != end; ++it) {
340                         const Model::Hit& hit = *it;
341                         const Vec3 position = hit.target<Vec3>();
342                         m_handleManager.deselectFaceHandle(position);
343                     }
344                 }
345             }
346         }
347 
actionName() const348         String VertexTool::actionName() const {
349             if (m_mode == Mode_Move) {
350                 assert((m_handleManager.selectedVertexHandles().empty() ? 0 : 1) +
351                        (m_handleManager.selectedEdgeHandles().empty() ? 0 : 1) +
352                        (m_handleManager.selectedFaceHandles().empty() ? 0 : 1) == 1);
353 
354                 if (!m_handleManager.selectedVertexHandles().empty())
355                     return m_handleManager.selectedVertexHandles().size() == 1 ? "Move Vertex" : "Move Vertices";
356                 if (!m_handleManager.selectedEdgeHandles().empty())
357                     return m_handleManager.selectedEdgeHandles().size() == 1 ? "Move Edge" : "Move Edges";
358                 return m_handleManager.selectedFaceHandles().size() == 1 ? "Move Face" : "Move Faces";
359             }
360 
361             assert(m_handleManager.selectedVertexHandles().size() == 0 &&
362                    ((m_handleManager.selectedEdgeHandles().size() == 1) ^
363                     (m_handleManager.selectedFaceHandles().size() == 1))
364                    );
365 
366             if (!m_handleManager.selectedEdgeHandles().empty())
367                 return "Split Edge";
368             return "Split Face";
369         }
370 
moveVertices(const Vec3 & delta)371         VertexTool::MoveResult VertexTool::moveVertices(const Vec3& delta) {
372             if (m_mode == Mode_Move) {
373                 assert((m_handleManager.selectedVertexCount() > 0) ^
374                        (m_handleManager.selectedEdgeCount() > 0) ^
375                        (m_handleManager.selectedFaceCount() > 0));
376 
377                 if (m_handleManager.selectedVertexCount() > 0)
378                     return doMoveVertices(delta);
379                 else if (m_handleManager.selectedEdgeCount() > 0)
380                     return doMoveEdges(delta);
381                 else if (m_handleManager.selectedFaceCount() > 0)
382                     return doMoveFaces(delta);
383             } else {
384                 assert((m_handleManager.selectedVertexCount() == 0) &&
385                        ((m_handleManager.selectedEdgeCount() == 1) ^
386                         (m_handleManager.selectedFaceCount() == 1)));
387 
388                 if (m_handleManager.selectedEdgeCount() > 0) {
389                     return doSplitEdges(delta);
390                 } else if (m_handleManager.selectedFaceCount() > 0) {
391                     return doSplitFaces(delta);
392                 }
393             }
394             return MR_Continue;
395         }
396 
doMoveVertices(const Vec3 & delta)397         VertexTool::MoveResult VertexTool::doMoveVertices(const Vec3& delta) {
398             MapDocumentSPtr document = lock(m_document);
399             const MapDocument::MoveVerticesResult result = document->moveVertices(m_handleManager.selectedVertexHandles(), delta);
400             if (result.success) {
401                 if (!result.hasRemainingVertices)
402                     return MR_Cancel;
403                 m_dragHandlePosition += delta;
404                 return MR_Continue;
405             }
406             return MR_Deny;
407         }
408 
doMoveEdges(const Vec3 & delta)409         VertexTool::MoveResult VertexTool::doMoveEdges(const Vec3& delta) {
410             MapDocumentSPtr document = lock(m_document);
411             if (document->moveEdges(m_handleManager.selectedEdgeHandles(), delta)) {
412                 m_dragHandlePosition += delta;
413                 return MR_Continue;
414             }
415             return MR_Deny;
416         }
417 
doMoveFaces(const Vec3 & delta)418         VertexTool::MoveResult VertexTool::doMoveFaces(const Vec3& delta) {
419             MapDocumentSPtr document = lock(m_document);
420             if (document->moveFaces(m_handleManager.selectedFaceHandles(), delta)) {
421                 m_dragHandlePosition += delta;
422                 return MR_Continue;
423             }
424             return MR_Deny;
425         }
426 
doSplitEdges(const Vec3 & delta)427         VertexTool::MoveResult VertexTool::doSplitEdges(const Vec3& delta) {
428             MapDocumentSPtr document = lock(m_document);
429             if (document->splitEdges(m_handleManager.selectedEdgeHandles(), delta)) {
430                 m_mode = Mode_Move;
431                 m_dragHandlePosition += delta;
432                 return MR_Continue;
433             }
434             return MR_Deny;
435         }
436 
doSplitFaces(const Vec3 & delta)437         VertexTool::MoveResult VertexTool::doSplitFaces(const Vec3& delta) {
438             MapDocumentSPtr document = lock(m_document);
439             if (document->splitFaces(m_handleManager.selectedFaceHandles(), delta)) {
440                 m_mode = Mode_Move;
441                 m_dragHandlePosition += delta;
442                 return MR_Continue;
443             }
444             return MR_Deny;
445         }
446 
rebuildBrushGeometry()447         void VertexTool::rebuildBrushGeometry() {
448             MapDocumentSPtr document = lock(m_document);
449 
450             const SetBool ignoreChangeNotifications(m_ignoreChangeNotifications);
451 
452             const Vec3::List selectedVertexHandles = m_handleManager.selectedVertexHandlePositions();
453             const Vec3::List selectedEdgeHandles   = m_handleManager.selectedEdgeHandlePositions();
454             const Vec3::List selectedFaceHandles   = m_handleManager.selectedFaceHandlePositions();
455 
456             const Model::BrushSet brushes = m_handleManager.selectedBrushes();
457 
458             m_handleManager.removeBrushes(brushes.begin(), brushes.end());
459             document->rebuildBrushGeometry(Model::BrushList(brushes.begin(), brushes.end()));
460             m_handleManager.addBrushes(brushes.begin(), brushes.end());
461 
462             m_handleManager.reselectVertexHandles(brushes, selectedVertexHandles, 0.01);
463             m_handleManager.reselectEdgeHandles(brushes, selectedEdgeHandles, 0.01);
464             m_handleManager.reselectFaceHandles(brushes, selectedFaceHandles, 0.01);
465         }
466 
doActivate()467         bool VertexTool::doActivate() {
468             MapDocumentSPtr document = lock(m_document);
469             m_mode = Mode_Move;
470             m_handleManager.clear();
471 
472             const Model::BrushList& selectedBrushes = document->selectedNodes().brushes();
473             m_handleManager.addBrushes(selectedBrushes.begin(), selectedBrushes.end());
474             m_changeCount = 0;
475 
476             bindObservers();
477             return true;
478         }
479 
doDeactivate()480         bool VertexTool::doDeactivate() {
481             unbindObservers();
482             m_handleManager.clear();
483 
484             /*
485              if (m_changeCount > 0) {
486              RebuildBrushGeometryCommand* command = RebuildBrushGeometryCommand::rebuildGeometry(document, document.editStateManager().selectedBrushes(), m_changeCount);
487              submitCommand(command);
488              }
489              */
490             return true;
491         }
492 
bindObservers()493         void VertexTool::bindObservers() {
494             MapDocumentSPtr document = lock(m_document);
495             document->selectionDidChangeNotifier.addObserver(this, &VertexTool::selectionDidChange);
496             document->nodesWillChangeNotifier.addObserver(this, &VertexTool::nodesWillChange);
497             document->nodesDidChangeNotifier.addObserver(this, &VertexTool::nodesDidChange);
498             document->commandDoNotifier.addObserver(this, &VertexTool::commandDo);
499             document->commandDoneNotifier.addObserver(this, &VertexTool::commandDone);
500             document->commandDoFailedNotifier.addObserver(this, &VertexTool::commandDoFailed);
501             document->commandUndoNotifier.addObserver(this, &VertexTool::commandUndo);
502             document->commandUndoneNotifier.addObserver(this, &VertexTool::commandUndone);
503             document->commandUndoFailedNotifier.addObserver(this, &VertexTool::commandUndoFailed);
504         }
505 
unbindObservers()506         void VertexTool::unbindObservers() {
507             if (!expired(m_document)) {
508                 MapDocumentSPtr document = lock(m_document);
509                 document->selectionDidChangeNotifier.removeObserver(this, &VertexTool::selectionDidChange);
510                 document->nodesWillChangeNotifier.removeObserver(this, &VertexTool::nodesWillChange);
511                 document->nodesDidChangeNotifier.removeObserver(this, &VertexTool::nodesDidChange);
512                 document->commandDoNotifier.removeObserver(this, &VertexTool::commandDo);
513                 document->commandDoneNotifier.removeObserver(this, &VertexTool::commandDone);
514                 document->commandDoFailedNotifier.removeObserver(this, &VertexTool::commandDoFailed);
515                 document->commandUndoNotifier.removeObserver(this, &VertexTool::commandUndo);
516                 document->commandUndoneNotifier.removeObserver(this, &VertexTool::commandUndone);
517                 document->commandUndoFailedNotifier.removeObserver(this, &VertexTool::commandUndoFailed);
518             }
519         }
520 
commandDo(Command::Ptr command)521         void VertexTool::commandDo(Command::Ptr command) {
522             commandDoOrUndo(command);
523         }
524 
commandDone(Command::Ptr command)525         void VertexTool::commandDone(Command::Ptr command) {
526             commandDoneOrUndoFailed(command);
527         }
528 
commandDoFailed(Command::Ptr command)529         void VertexTool::commandDoFailed(Command::Ptr command) {
530             commandDoFailedOrUndone(command);
531         }
532 
commandUndo(UndoableCommand::Ptr command)533         void VertexTool::commandUndo(UndoableCommand::Ptr command) {
534             commandDoOrUndo(command);
535         }
536 
commandUndone(UndoableCommand::Ptr command)537         void VertexTool::commandUndone(UndoableCommand::Ptr command) {
538             commandDoFailedOrUndone(command);
539         }
540 
commandUndoFailed(UndoableCommand::Ptr command)541         void VertexTool::commandUndoFailed(UndoableCommand::Ptr command) {
542             commandDoneOrUndoFailed(command);
543         }
544 
commandDoOrUndo(Command::Ptr command)545         void VertexTool::commandDoOrUndo(Command::Ptr command) {
546             if (isVertexCommand(command)) {
547                 VertexCommand* vertexCommand = static_cast<VertexCommand*>(command.get());
548                 vertexCommand->removeBrushes(m_handleManager);
549                 m_ignoreChangeNotifications = true;
550             }
551         }
552 
commandDoneOrUndoFailed(Command::Ptr command)553         void VertexTool::commandDoneOrUndoFailed(Command::Ptr command) {
554             if (isVertexCommand(command)) {
555                 VertexCommand* vertexCommand = static_cast<VertexCommand*>(command.get());
556                 vertexCommand->addBrushes(m_handleManager);
557                 vertexCommand->selectNewHandlePositions(m_handleManager);
558                 m_ignoreChangeNotifications = false;
559 
560                 if (!m_dragging)
561                     rebuildBrushGeometry();
562             }
563         }
564 
commandDoFailedOrUndone(Command::Ptr command)565         void VertexTool::commandDoFailedOrUndone(Command::Ptr command) {
566             if (isVertexCommand(command)) {
567                 VertexCommand* vertexCommand = static_cast<VertexCommand*>(command.get());
568                 vertexCommand->addBrushes(m_handleManager);
569                 vertexCommand->selectOldHandlePositions(m_handleManager);
570                 m_ignoreChangeNotifications = false;
571 
572                 if (!m_dragging)
573                     rebuildBrushGeometry();
574             }
575         }
576 
isVertexCommand(const Command::Ptr command) const577         bool VertexTool::isVertexCommand(const Command::Ptr command) const {
578             return (command->type() == SnapBrushVerticesCommand::Type ||
579                     command->type() == MoveBrushVerticesCommand::Type ||
580                     command->type() == MoveBrushEdgesCommand::Type ||
581                     command->type() == MoveBrushFacesCommand::Type ||
582                     command->type() == SplitBrushEdgesCommand::Type ||
583                     command->type() == SplitBrushFacesCommand::Type);
584         }
585 
586         class AddToHandleManager : public Model::NodeVisitor {
587         private:
588             VertexHandleManager& m_handleManager;
589         public:
AddToHandleManager(VertexHandleManager & handleManager)590             AddToHandleManager(VertexHandleManager& handleManager) :
591             m_handleManager(handleManager) {}
592         private:
doVisit(Model::World * world)593             void doVisit(Model::World* world)   {}
doVisit(Model::Layer * layer)594             void doVisit(Model::Layer* layer)   {}
doVisit(Model::Group * group)595             void doVisit(Model::Group* group)   {}
doVisit(Model::Entity * entity)596             void doVisit(Model::Entity* entity) {}
doVisit(Model::Brush * brush)597             void doVisit(Model::Brush* brush)   { m_handleManager.addBrush(brush); }
598         };
599 
600         class RemoveFromHandleManager : public Model::NodeVisitor {
601         private:
602             VertexHandleManager& m_handleManager;
603         public:
RemoveFromHandleManager(VertexHandleManager & handleManager)604             RemoveFromHandleManager(VertexHandleManager& handleManager) :
605             m_handleManager(handleManager) {}
606         private:
doVisit(Model::World * world)607             void doVisit(Model::World* world)   {}
doVisit(Model::Layer * layer)608             void doVisit(Model::Layer* layer)   {}
doVisit(Model::Group * group)609             void doVisit(Model::Group* group)   {}
doVisit(Model::Entity * entity)610             void doVisit(Model::Entity* entity) {}
doVisit(Model::Brush * brush)611             void doVisit(Model::Brush* brush)   { m_handleManager.removeBrush(brush); }
612         };
613 
selectionDidChange(const Selection & selection)614         void VertexTool::selectionDidChange(const Selection& selection) {
615             const Model::NodeList& selectedNodes = selection.selectedNodes();
616             AddToHandleManager addVisitor(m_handleManager);
617             Model::Node::accept(selectedNodes.begin(), selectedNodes.end(), addVisitor);
618 
619             const Model::NodeList& deselectedNodes = selection.deselectedNodes();
620             RemoveFromHandleManager removeVisitor(m_handleManager);
621             Model::Node::accept(deselectedNodes.begin(), deselectedNodes.end(), removeVisitor);
622         }
623 
nodesWillChange(const Model::NodeList & nodes)624         void VertexTool::nodesWillChange(const Model::NodeList& nodes) {
625             if (!m_ignoreChangeNotifications) {
626                 RemoveFromHandleManager removeVisitor(m_handleManager);
627                 Model::Node::accept(nodes.begin(), nodes.end(), removeVisitor);
628             }
629         }
630 
nodesDidChange(const Model::NodeList & nodes)631         void VertexTool::nodesDidChange(const Model::NodeList& nodes) {
632             if (!m_ignoreChangeNotifications) {
633                 AddToHandleManager addVisitor(m_handleManager);
634                 Model::Node::accept(nodes.begin(), nodes.end(), addVisitor);
635             }
636         }
637 
638 
doGetIconName() const639         String VertexTool::doGetIconName() const {
640             return "VertexTool.png";
641         }
642     }
643 }
644