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 "ReplaceTextureFrame.h" 21 22 #include "Assets/Texture.h" 23 #include "Model/BrushFace.h" 24 #include "Model/CollectMatchingBrushFacesVisitor.h" 25 #include "Model/World.h" 26 #include "View/BorderLine.h" 27 #include "View/MapDocument.h" 28 #include "View/TextureBrowser.h" 29 #include "View/TitledPanel.h" 30 #include "View/ViewConstants.h" 31 #include "View/wxUtils.h" 32 33 #include <wx/button.h> 34 #include <wx/msgdlg.h> 35 #include <wx/sizer.h> 36 37 namespace TrenchBroom { 38 namespace View { ReplaceTextureFrame(wxWindow * parent,MapDocumentWPtr document,GLContextManager & contextManager)39 ReplaceTextureFrame::ReplaceTextureFrame(wxWindow* parent, MapDocumentWPtr document, GLContextManager& contextManager) : 40 wxFrame(parent, wxID_ANY, "Replace Texture", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT), 41 m_document(document), 42 m_subjectBrowser(NULL), 43 m_replacementBrowser(NULL) { 44 createGui(contextManager); 45 } 46 OnReplace(wxCommandEvent & event)47 void ReplaceTextureFrame::OnReplace(wxCommandEvent& event) { 48 if (IsBeingDeleted()) return; 49 50 const Assets::Texture* subject = m_subjectBrowser->selectedTexture(); 51 assert(subject != NULL); 52 53 Assets::Texture* replacement = m_replacementBrowser->selectedTexture(); 54 assert(replacement != NULL); 55 56 MapDocumentSPtr document = lock(m_document); 57 const Model::BrushFaceList faces = getApplicableFaces(); 58 59 if (faces.empty()) { 60 wxMessageBox("None of the selected faces has the selected texture", "Replace Failed"); 61 return; 62 } 63 64 Transaction transaction(document, "Replace Textures"); 65 document->select(faces); 66 document->setTexture(replacement); 67 68 StringStream msg; 69 msg << "Replaced texture '" << subject->name() << "' with '" << replacement->name() << "' on " << faces.size() << " faces."; 70 wxMessageBox(msg.str(), "Replace succeeded"); 71 } 72 getApplicableFaces() const73 Model::BrushFaceList ReplaceTextureFrame::getApplicableFaces() const { 74 MapDocumentSPtr document = lock(m_document); 75 Model::BrushFaceList faces = document->allSelectedBrushFaces(); 76 if (faces.empty()) { 77 Model::CollectBrushFacesVisitor collect; 78 document->world()->acceptAndRecurse(collect); 79 faces = collect.faces(); 80 } 81 82 const Assets::Texture* subject = m_subjectBrowser->selectedTexture(); 83 assert(subject != NULL); 84 85 Model::BrushFaceList result; 86 87 Model::BrushFaceList::const_iterator it, end; 88 for (it = faces.begin(), end = faces.end(); it != end; ++it) { 89 Model::BrushFace* face = *it; 90 if (face->texture() == subject) 91 result.push_back(face); 92 } 93 return result; 94 } 95 OnClose(wxCommandEvent & event)96 void ReplaceTextureFrame::OnClose(wxCommandEvent& event) { 97 if (IsBeingDeleted()) return; 98 99 Close(); 100 } 101 OnUpdateReplaceButton(wxUpdateUIEvent & event)102 void ReplaceTextureFrame::OnUpdateReplaceButton(wxUpdateUIEvent& event) { 103 if (IsBeingDeleted()) return; 104 105 const Assets::Texture* subject = m_subjectBrowser->selectedTexture(); 106 const Assets::Texture* replacement = m_replacementBrowser->selectedTexture(); 107 event.Enable(subject != NULL && replacement != NULL); 108 } 109 createGui(GLContextManager & contextManager)110 void ReplaceTextureFrame::createGui(GLContextManager& contextManager) { 111 TitledPanel* subjectPanel = new TitledPanel(this, "Find"); 112 m_subjectBrowser = new TextureBrowser(subjectPanel->getPanel(), m_document, contextManager); 113 m_subjectBrowser->setHideUnused(true); 114 115 wxSizer* subjectPanelSizer = new wxBoxSizer(wxVERTICAL); 116 subjectPanelSizer->Add(m_subjectBrowser, 1, wxEXPAND); 117 subjectPanel->getPanel()->SetSizer(subjectPanelSizer); 118 119 TitledPanel* replacementPanel = new TitledPanel(this, "Replace with"); 120 m_replacementBrowser = new TextureBrowser(replacementPanel->getPanel(), m_document, contextManager); 121 122 wxSizer* replacementPanelSizer = new wxBoxSizer(wxVERTICAL); 123 replacementPanelSizer->Add(m_replacementBrowser, 1, wxEXPAND); 124 replacementPanel->getPanel()->SetSizer(replacementPanelSizer); 125 126 wxSizer* upperSizer = new wxBoxSizer(wxHORIZONTAL); 127 upperSizer->Add(subjectPanel, 1, wxEXPAND); 128 upperSizer->Add(new BorderLine(this, BorderLine::Direction_Vertical), 0, wxEXPAND); 129 upperSizer->Add(replacementPanel, 1, wxEXPAND); 130 131 wxButton* replaceButton = new wxButton(this, wxID_OK, "Replace"); 132 replaceButton->SetToolTip("Perform replacement on all selected faces"); 133 wxButton* closeButton = new wxButton(this, wxID_CLOSE, "Close"); 134 closeButton->SetToolTip("Close this window"); 135 136 replaceButton->Bind(wxEVT_BUTTON, &ReplaceTextureFrame::OnReplace, this); 137 closeButton->Bind(wxEVT_BUTTON, &ReplaceTextureFrame::OnClose, this); 138 139 replaceButton->Bind(wxEVT_UPDATE_UI, &ReplaceTextureFrame::OnUpdateReplaceButton, this); 140 141 wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer(); 142 buttonSizer->AddButton(replaceButton); 143 buttonSizer->AddButton(closeButton); 144 buttonSizer->Realize(); 145 146 wxSizer* outerSizer = new wxBoxSizer(wxVERTICAL); 147 outerSizer->Add(upperSizer, 1, wxEXPAND); 148 outerSizer->Add(wrapDialogButtonSizer(buttonSizer, this), 0, wxEXPAND); 149 SetSizer(outerSizer); 150 151 wxAcceleratorEntry entries[] = { 152 wxAcceleratorEntry(wxACCEL_CTRL, 'W', wxID_CLOSE) 153 }; 154 SetAcceleratorTable(wxAcceleratorTable(1, entries)); 155 Bind(wxEVT_MENU, &ReplaceTextureFrame::OnClose, this, wxID_CLOSE); 156 157 SetMinSize(wxSize(650, 450)); 158 SetSize(wxSize(650, 450)); 159 } 160 } 161 } 162