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