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 "UVShearTool.h" 21 22 #include "Model/BrushFace.h" 23 #include "Model/ChangeBrushFaceAttributesRequest.h" 24 #include "Model/PickResult.h" 25 #include "View/InputState.h" 26 #include "View/MapDocument.h" 27 #include "View/UVViewHelper.h" 28 29 namespace TrenchBroom { 30 namespace View { 31 const Model::Hit::HitType UVShearTool::XHandleHit = Model::Hit::freeHitType(); 32 const Model::Hit::HitType UVShearTool::YHandleHit = Model::Hit::freeHitType(); 33 UVShearTool(MapDocumentWPtr document,UVViewHelper & helper)34 UVShearTool::UVShearTool(MapDocumentWPtr document, UVViewHelper& helper) : 35 ToolControllerBase(), 36 Tool(true), 37 m_document(document), 38 m_helper(helper) {} 39 doGetTool()40 Tool* UVShearTool::doGetTool() { 41 return this; 42 } 43 doPick(const InputState & inputState,Model::PickResult & pickResult)44 void UVShearTool::doPick(const InputState& inputState, Model::PickResult& pickResult) { 45 static const Model::Hit::HitType HitTypes[] = { XHandleHit, YHandleHit }; 46 if (m_helper.valid()) 47 m_helper.pickTextureGrid(inputState.pickRay(), HitTypes, pickResult); 48 } 49 doStartMouseDrag(const InputState & inputState)50 bool UVShearTool::doStartMouseDrag(const InputState& inputState) { 51 assert(m_helper.valid()); 52 53 if (!inputState.modifierKeysPressed(ModifierKeys::MKAlt) || 54 !inputState.mouseButtonsPressed(MouseButtons::MBLeft)) 55 return false; 56 57 const Model::PickResult& pickResult = inputState.pickResult(); 58 const Model::Hit& xHit = pickResult.query().type(XHandleHit).occluded().first(); 59 const Model::Hit& yHit = pickResult.query().type(YHandleHit).occluded().first(); 60 61 if (!(xHit.isMatch() ^ yHit.isMatch())) 62 return false; 63 64 m_selector = Vec2b(xHit.isMatch(), yHit.isMatch()); 65 66 const Model::BrushFace* face = m_helper.face(); 67 m_xAxis = face->textureXAxis(); 68 m_yAxis = face->textureYAxis(); 69 m_initialHit = m_lastHit = getHit(inputState.pickRay()); 70 71 MapDocumentSPtr document = lock(m_document); 72 document->beginTransaction("Shear Texture"); 73 return true; 74 } 75 doMouseDrag(const InputState & inputState)76 bool UVShearTool::doMouseDrag(const InputState& inputState) { 77 const Vec2f currentHit = getHit(inputState.pickRay()); 78 const Vec2f delta = currentHit - m_lastHit; 79 80 Model::BrushFace* face = m_helper.face(); 81 const Vec3 origin = m_helper.origin(); 82 const Vec2f oldCoords = face->toTexCoordSystemMatrix(Vec2f::Null, face->scale(), true) * origin; 83 84 MapDocumentSPtr document = lock(m_document); 85 if (m_selector[0]) { 86 const Vec2f factors = Vec2f(-delta.y() / m_initialHit.x(), 0.0f); 87 if (!factors.null()) 88 document->shearTextures(factors); 89 } else if (m_selector[1]) { 90 const Vec2f factors = Vec2f(0.0f, -delta.x() / m_initialHit.y()); 91 if (!factors.null()) 92 document->shearTextures(factors); 93 } 94 95 const Vec2f newCoords = face->toTexCoordSystemMatrix(Vec2f::Null, face->scale(), true) * origin; 96 const Vec2f newOffset = face->offset() + oldCoords - newCoords; 97 98 Model::ChangeBrushFaceAttributesRequest request; 99 request.setOffset(newOffset); 100 document->setFaceAttributes(request); 101 102 const Vec3 newOrigin = face->toTexCoordSystemMatrix(Vec2f::Null, Vec2f::One, true) * origin; 103 m_helper.setOrigin(newOrigin); 104 105 m_lastHit = currentHit; 106 return true; 107 } 108 doEndMouseDrag(const InputState & inputState)109 void UVShearTool::doEndMouseDrag(const InputState& inputState) { 110 MapDocumentSPtr document = lock(m_document); 111 document->commitTransaction(); 112 } 113 doCancelMouseDrag()114 void UVShearTool::doCancelMouseDrag() { 115 MapDocumentSPtr document = lock(m_document); 116 document->cancelTransaction(); 117 } 118 getHit(const Ray3 & pickRay) const119 Vec2f UVShearTool::getHit(const Ray3& pickRay) const { 120 const Model::BrushFace* face = m_helper.face(); 121 const Plane3& boundary = face->boundary(); 122 const FloatType hitPointDist = boundary.intersectWithRay(pickRay); 123 const Vec3 hitPoint = pickRay.pointAtDistance(hitPointDist); 124 const Vec3 hitVec = hitPoint - m_helper.origin(); 125 126 return Vec2f(hitVec.dot(m_xAxis), 127 hitVec.dot(m_yAxis)); 128 } 129 doCancel()130 bool UVShearTool::doCancel() { 131 return false; 132 } 133 } 134 } 135