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 "RotateObjectsToolPage.h" 21 22 #include "View/BorderLine.h" 23 #include "View/Grid.h" 24 #include "View/MapDocument.h" 25 #include "View/RotateObjectsTool.h" 26 #include "View/SpinControl.h" 27 #include "View/ViewConstants.h" 28 29 #include <wx/button.h> 30 #include <wx/choice.h> 31 #include <wx/sizer.h> 32 #include <wx/stattext.h> 33 #include <wx/textctrl.h> 34 35 namespace TrenchBroom { 36 namespace View { RotateObjectsToolPage(wxWindow * parent,MapDocumentWPtr document,RotateObjectsTool * tool)37 RotateObjectsToolPage::RotateObjectsToolPage(wxWindow* parent, MapDocumentWPtr document, RotateObjectsTool* tool) : 38 wxPanel(parent), 39 m_document(document), 40 m_tool(tool) { 41 createGui(); 42 m_angle->SetValue(Math::degrees(m_tool->angle())); 43 } 44 setAxis(const Math::Axis::Type axis)45 void RotateObjectsToolPage::setAxis(const Math::Axis::Type axis) { 46 m_axis->SetSelection(static_cast<int>(axis)); 47 } 48 setCenter(const Vec3 & center)49 void RotateObjectsToolPage::setCenter(const Vec3& center) { 50 m_centerTxt->SetValue(center.asString()); 51 } 52 createGui()53 void RotateObjectsToolPage::createGui() { 54 wxStaticText* centerText = new wxStaticText(this, wxID_ANY, "Center"); 55 m_centerTxt = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); 56 m_centerTxt->SetToolTip("Hit Return to set the rotate handle to the entered coordinates."); 57 58 m_resetCenterButton = new wxButton(this, wxID_ANY, "Reset", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); 59 m_resetCenterButton->SetToolTip("Reset the position of the rotate handle to the center of the current selection."); 60 61 wxStaticText* text1 = new wxStaticText(this, wxID_ANY, "Rotate objects"); 62 wxStaticText* text2 = new wxStaticText(this, wxID_ANY, "degs about"); 63 wxStaticText* text3 = new wxStaticText(this, wxID_ANY, "axis"); 64 m_angle = new SpinControl(this); 65 m_angle->SetRange(-360.0, 360.0); 66 m_angle->SetValue(Math::degrees(m_tool->angle())); 67 m_angle->SetDigits(0, 2); 68 69 wxString axes[] = { "X", "Y", "Z" }; 70 m_axis = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 3, axes); 71 m_axis->SetSelection(2); 72 73 m_rotateButton = new wxButton(this, wxID_ANY, "Apply", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); 74 75 Bind(wxEVT_IDLE, &RotateObjectsToolPage::OnIdle, this); 76 m_centerTxt->Bind(wxEVT_TEXT_ENTER, &RotateObjectsToolPage::OnCenterChanged, this); 77 m_resetCenterButton->Bind(wxEVT_BUTTON, &RotateObjectsToolPage::OnResetCenter, this); 78 m_angle->Bind(SPIN_CONTROL_EVENT, &RotateObjectsToolPage::OnAngleChanged, this); 79 m_rotateButton->Bind(wxEVT_UPDATE_UI, &RotateObjectsToolPage::OnUpdateRotateButton, this); 80 m_rotateButton->Bind(wxEVT_BUTTON, &RotateObjectsToolPage::OnRotate, this); 81 82 BorderLine* separator = new BorderLine(this, BorderLine::Direction_Vertical); 83 separator->SetForegroundColour(Colors::separatorColor()); 84 85 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); 86 sizer->Add(centerText, 0, wxALIGN_CENTER_VERTICAL); 87 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 88 sizer->Add(m_centerTxt, 0, wxALIGN_CENTER_VERTICAL); 89 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 90 sizer->Add(m_resetCenterButton, 0, wxALIGN_CENTER_VERTICAL); 91 sizer->AddSpacer(LayoutConstants::MediumHMargin); 92 sizer->Add(separator, 0, wxEXPAND | wxTOP | wxBOTTOM, 2); 93 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 94 sizer->Add(text1, 0, wxALIGN_CENTER_VERTICAL); 95 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 96 sizer->Add(m_angle, 0, wxALIGN_CENTER_VERTICAL); 97 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 98 sizer->Add(text2, 0, wxALIGN_CENTER_VERTICAL); 99 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 100 sizer->Add(m_axis, 0, wxTOP, LayoutConstants::ChoiceTopMargin); 101 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 102 sizer->Add(text3, 0, wxALIGN_CENTER_VERTICAL); 103 sizer->AddSpacer(LayoutConstants::NarrowHMargin); 104 sizer->Add(m_rotateButton, 0, wxALIGN_CENTER_VERTICAL); 105 sizer->SetItemMinSize(m_angle, 80, wxDefaultCoord); 106 107 SetSizer(sizer); 108 } 109 OnIdle(wxIdleEvent & event)110 void RotateObjectsToolPage::OnIdle(wxIdleEvent& event) { 111 if (IsBeingDeleted()) return; 112 113 const Grid& grid = lock(m_document)->grid(); 114 m_angle->SetIncrements(Math::degrees(grid.angle()), 90.0, 1.0); 115 } 116 OnCenterChanged(wxCommandEvent & event)117 void RotateObjectsToolPage::OnCenterChanged(wxCommandEvent& event) { 118 if (IsBeingDeleted()) return; 119 120 const Vec3 center = Vec3::parse(m_centerTxt->GetValue().ToStdString()); 121 m_tool->setRotationCenter(center); 122 } 123 OnResetCenter(wxCommandEvent & event)124 void RotateObjectsToolPage::OnResetCenter(wxCommandEvent& event) { 125 if (IsBeingDeleted()) return; 126 127 m_tool->resetRotationCenter(); 128 } 129 OnAngleChanged(SpinControlEvent & event)130 void RotateObjectsToolPage::OnAngleChanged(SpinControlEvent& event) { 131 if (IsBeingDeleted()) return; 132 133 const double newAngleDegs = Math::correct(event.IsSpin() ? m_angle->GetValue() + event.GetValue() : event.GetValue()); 134 m_angle->SetValue(newAngleDegs); 135 m_tool->setAngle(Math::radians(newAngleDegs)); 136 } 137 OnUpdateRotateButton(wxUpdateUIEvent & event)138 void RotateObjectsToolPage::OnUpdateRotateButton(wxUpdateUIEvent& event) { 139 if (IsBeingDeleted()) return; 140 141 MapDocumentSPtr document = lock(m_document); 142 event.Enable(document->hasSelectedNodes()); 143 } 144 OnRotate(wxCommandEvent & event)145 void RotateObjectsToolPage::OnRotate(wxCommandEvent& event) { 146 if (IsBeingDeleted()) return; 147 148 const Vec3 center = m_tool->rotationCenter(); 149 const Vec3 axis = getAxis(); 150 const FloatType angle = Math::radians(m_angle->GetValue()); 151 152 MapDocumentSPtr document = lock(m_document); 153 document->rotateObjects(center, axis, angle); 154 } 155 getAxis() const156 Vec3 RotateObjectsToolPage::getAxis() const { 157 switch (m_axis->GetSelection()) { 158 case 0: 159 return Vec3::PosX; 160 case 1: 161 return Vec3::PosY; 162 default: 163 return Vec3::PosZ; 164 } 165 } 166 } 167 } 168