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 "FaceAttribsEditor.h" 21 22 #include "Assets/AssetTypes.h" 23 #include "Assets/Texture.h" 24 #include "IO/Path.h" 25 #include "IO/ResourceUtils.h" 26 #include "Model/BrushFace.h" 27 #include "Model/ChangeBrushFaceAttributesRequest.h" 28 #include "Model/Game.h" 29 #include "Model/GameConfig.h" 30 #include "View/BorderLine.h" 31 #include "View/FlagChangedCommand.h" 32 #include "View/FlagsPopupEditor.h" 33 #include "View/Grid.h" 34 #include "View/ViewConstants.h" 35 #include "View/MapDocument.h" 36 #include "View/SpinControl.h" 37 #include "View/UVEditor.h" 38 #include "View/ViewUtils.h" 39 40 #include <wx/bitmap.h> 41 #include <wx/button.h> 42 #include <wx/gbsizer.h> 43 #include <wx/sizer.h> 44 #include <wx/stattext.h> 45 46 namespace TrenchBroom { 47 namespace View { FaceAttribsEditor(wxWindow * parent,MapDocumentWPtr document,GLContextManager & contextManager)48 FaceAttribsEditor::FaceAttribsEditor(wxWindow* parent, MapDocumentWPtr document, GLContextManager& contextManager) : 49 wxPanel(parent), 50 m_document(document), 51 m_uvEditor(NULL), 52 m_xOffsetEditor(NULL), 53 m_yOffsetEditor(NULL), 54 m_xScaleEditor(NULL), 55 m_yScaleEditor(NULL), 56 m_rotationEditor(NULL), 57 m_surfaceValueLabel(NULL), 58 m_surfaceValueEditor(NULL), 59 m_faceAttribsSizer(NULL), 60 m_surfaceFlagsLabel(NULL), 61 m_surfaceFlagsEditor(NULL), 62 m_contentFlagsLabel(NULL), 63 m_contentFlagsEditor(NULL) { 64 createGui(contextManager); 65 bindEvents(); 66 bindObservers(); 67 } 68 ~FaceAttribsEditor()69 FaceAttribsEditor::~FaceAttribsEditor() { 70 unbindObservers(); 71 } 72 OnXOffsetChanged(SpinControlEvent & event)73 void FaceAttribsEditor::OnXOffsetChanged(SpinControlEvent& event) { 74 if (IsBeingDeleted()) return; 75 76 Model::ChangeBrushFaceAttributesRequest request; 77 if (event.IsSpin()) 78 request.addXOffset(static_cast<float>(event.GetValue())); 79 else 80 request.setXOffset(static_cast<float>(event.GetValue())); 81 82 MapDocumentSPtr document = lock(m_document); 83 if (!document->setFaceAttributes(request) || event.IsSpin()) 84 event.Veto(); 85 } 86 OnYOffsetChanged(SpinControlEvent & event)87 void FaceAttribsEditor::OnYOffsetChanged(SpinControlEvent& event) { 88 if (IsBeingDeleted()) return; 89 90 Model::ChangeBrushFaceAttributesRequest request; 91 if (event.IsSpin()) 92 request.addYOffset(static_cast<float>(event.GetValue())); 93 else 94 request.setYOffset(static_cast<float>(event.GetValue())); 95 96 MapDocumentSPtr document = lock(m_document); 97 if (!document->setFaceAttributes(request) || event.IsSpin()) 98 event.Veto(); 99 } 100 OnRotationChanged(SpinControlEvent & event)101 void FaceAttribsEditor::OnRotationChanged(SpinControlEvent& event) { 102 if (IsBeingDeleted()) return; 103 104 Model::ChangeBrushFaceAttributesRequest request; 105 if (event.IsSpin()) 106 request.addRotation(static_cast<float>(event.GetValue())); 107 else 108 request.setRotation(static_cast<float>(event.GetValue())); 109 110 MapDocumentSPtr document = lock(m_document); 111 if (!document->setFaceAttributes(request) || event.IsSpin()) 112 event.Veto(); 113 } 114 OnXScaleChanged(SpinControlEvent & event)115 void FaceAttribsEditor::OnXScaleChanged(SpinControlEvent& event) { 116 if (IsBeingDeleted()) return; 117 118 Model::ChangeBrushFaceAttributesRequest request; 119 if (event.IsSpin()) 120 request.addXScale(static_cast<float>(event.GetValue())); 121 else 122 request.setXScale(static_cast<float>(event.GetValue())); 123 124 MapDocumentSPtr document = lock(m_document); 125 if (!document->setFaceAttributes(request) || event.IsSpin()) 126 event.Veto(); 127 } 128 OnYScaleChanged(SpinControlEvent & event)129 void FaceAttribsEditor::OnYScaleChanged(SpinControlEvent& event) { 130 if (IsBeingDeleted()) return; 131 132 Model::ChangeBrushFaceAttributesRequest request; 133 if (event.IsSpin()) 134 request.addYScale(static_cast<float>(event.GetValue())); 135 else 136 request.setYScale(static_cast<float>(event.GetValue())); 137 138 MapDocumentSPtr document = lock(m_document); 139 if (!document->setFaceAttributes(request) || event.IsSpin()) 140 event.Veto(); 141 } 142 OnSurfaceFlagChanged(FlagChangedCommand & command)143 void FaceAttribsEditor::OnSurfaceFlagChanged(FlagChangedCommand& command) { 144 if (IsBeingDeleted()) return; 145 146 Model::ChangeBrushFaceAttributesRequest request; 147 if (command.flagSet()) 148 request.setSurfaceFlag(command.index()); 149 else 150 request.unsetSurfaceFlag(command.index()); 151 152 MapDocumentSPtr document = lock(m_document); 153 if (!document->setFaceAttributes(request)) 154 command.Veto(); 155 } 156 OnContentFlagChanged(FlagChangedCommand & command)157 void FaceAttribsEditor::OnContentFlagChanged(FlagChangedCommand& command) { 158 if (IsBeingDeleted()) return; 159 160 Model::ChangeBrushFaceAttributesRequest request; 161 if (command.flagSet()) 162 request.setContentFlag(command.index()); 163 else 164 request.unsetContentFlag(command.index()); 165 166 MapDocumentSPtr document = lock(m_document); 167 if (!document->setFaceAttributes(request)) 168 command.Veto(); 169 } 170 OnSurfaceValueChanged(SpinControlEvent & event)171 void FaceAttribsEditor::OnSurfaceValueChanged(SpinControlEvent& event) { 172 if (IsBeingDeleted()) return; 173 174 Model::ChangeBrushFaceAttributesRequest request; 175 if (event.IsSpin()) 176 request.addSurfaceValue(static_cast<float>(event.GetValue())); 177 else 178 request.setSurfaceValue(static_cast<float>(event.GetValue())); 179 180 MapDocumentSPtr document = lock(m_document); 181 if (!document->setFaceAttributes(request) || event.IsSpin()) 182 event.Veto(); 183 } 184 OnIdle(wxIdleEvent & event)185 void FaceAttribsEditor::OnIdle(wxIdleEvent& event) { 186 if (IsBeingDeleted()) return; 187 188 MapDocumentSPtr document = lock(m_document); 189 Grid& grid = document->grid(); 190 191 m_xOffsetEditor->SetIncrements(grid.actualSize(), 2.0 * grid.actualSize(), 1.0); 192 m_yOffsetEditor->SetIncrements(grid.actualSize(), 2.0 * grid.actualSize(), 1.0); 193 m_rotationEditor->SetIncrements(Math::degrees(grid.angle()), 90.0, 1.0); 194 } 195 createGui(GLContextManager & contextManager)196 void FaceAttribsEditor::createGui(GLContextManager& contextManager) { 197 m_uvEditor = new UVEditor(this, m_document, contextManager); 198 199 wxStaticText* textureNameLabel = new wxStaticText(this, wxID_ANY, "Texture"); 200 textureNameLabel->SetFont(textureNameLabel->GetFont().Bold()); 201 m_textureName = new wxStaticText(this, wxID_ANY, "none"); 202 203 wxStaticText* textureSizeLabel = new wxStaticText(this, wxID_ANY, "Size"); 204 textureSizeLabel->SetFont(textureSizeLabel->GetFont().Bold()); 205 m_textureSize = new wxStaticText(this, wxID_ANY, ""); 206 207 const double max = std::numeric_limits<double>::max(); 208 const double min = -max; 209 210 wxStaticText* xOffsetLabel = new wxStaticText(this, wxID_ANY, "X Offset"); 211 xOffsetLabel->SetFont(xOffsetLabel->GetFont().Bold()); 212 m_xOffsetEditor = new SpinControl(this); 213 m_xOffsetEditor->SetRange(min, max); 214 m_xOffsetEditor->SetDigits(0, 6); 215 216 wxStaticText* yOffsetLabel = new wxStaticText(this, wxID_ANY, "Y Offset"); 217 yOffsetLabel->SetFont(yOffsetLabel->GetFont().Bold()); 218 m_yOffsetEditor = new SpinControl(this); 219 m_yOffsetEditor->SetRange(min, max); 220 m_yOffsetEditor->SetDigits(0, 6); 221 222 wxStaticText* xScaleLabel = new wxStaticText(this, wxID_ANY, "X Scale"); 223 xScaleLabel->SetFont(xScaleLabel->GetFont().Bold()); 224 m_xScaleEditor = new SpinControl(this); 225 m_xScaleEditor->SetRange(min, max); 226 m_xScaleEditor->SetIncrements(0.1, 0.25, 0.01); 227 m_xScaleEditor->SetDigits(0, 6); 228 229 wxStaticText* yScaleLabel = new wxStaticText(this, wxID_ANY, "Y Scale"); 230 yScaleLabel->SetFont(yScaleLabel->GetFont().Bold()); 231 m_yScaleEditor = new SpinControl(this); 232 m_yScaleEditor->SetRange(min, max); 233 m_yScaleEditor->SetIncrements(0.1, 0.25, 0.01); 234 m_yScaleEditor->SetDigits(0, 6); 235 236 wxStaticText* rotationLabel = new wxStaticText(this, wxID_ANY, "Angle"); 237 rotationLabel->SetFont(rotationLabel->GetFont().Bold()); 238 m_rotationEditor = new SpinControl(this); 239 m_rotationEditor->SetRange(min, max); 240 m_rotationEditor->SetDigits(0, 6); 241 242 m_surfaceValueLabel = new wxStaticText(this, wxID_ANY, "Value", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); 243 m_surfaceValueLabel->SetFont(m_surfaceValueLabel->GetFont().Bold()); 244 m_surfaceValueEditor = new SpinControl(this); 245 m_surfaceValueEditor->SetRange(min, max); 246 m_surfaceValueEditor->SetIncrements(1.0, 10.0, 100.0); 247 m_surfaceValueEditor->SetDigits(0, 6); 248 249 m_surfaceFlagsLabel = new wxStaticText(this, wxID_ANY, "Surface", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); 250 m_surfaceFlagsLabel->SetFont(m_surfaceFlagsLabel->GetFont().Bold()); 251 m_surfaceFlagsEditor = new FlagsPopupEditor(this, 2); 252 253 m_contentFlagsLabel = new wxStaticText(this, wxID_ANY, "Content", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); 254 m_contentFlagsLabel->SetFont(m_contentFlagsLabel->GetFont().Bold()); 255 m_contentFlagsEditor = new FlagsPopupEditor(this, 2); 256 257 const int LabelMargin = LayoutConstants::NarrowHMargin; 258 const int EditorMargin = LayoutConstants::WideHMargin; 259 const int RowMargin = LayoutConstants::NarrowVMargin; 260 261 const int LabelFlags = wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT; 262 const int ValueFlags = wxALIGN_CENTER_VERTICAL | wxRIGHT; 263 const int Editor1Flags = wxEXPAND | wxRIGHT; 264 const int Editor2Flags = wxEXPAND; 265 266 int r = 0; 267 int c = 0; 268 269 m_faceAttribsSizer = new wxGridBagSizer(RowMargin); 270 m_faceAttribsSizer->Add(textureNameLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 271 m_faceAttribsSizer->Add(m_textureName, wxGBPosition(r,c++), wxDefaultSpan, ValueFlags, EditorMargin); 272 m_faceAttribsSizer->Add(textureSizeLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 273 m_faceAttribsSizer->Add(m_textureSize, wxGBPosition(r,c++), wxDefaultSpan, ValueFlags, EditorMargin); 274 ++r, c = 0; 275 276 m_faceAttribsSizer->Add(xOffsetLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 277 m_faceAttribsSizer->Add(m_xOffsetEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor1Flags, EditorMargin); 278 m_faceAttribsSizer->Add(yOffsetLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 279 m_faceAttribsSizer->Add(m_yOffsetEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor2Flags, EditorMargin); 280 ++r; c = 0; 281 282 m_faceAttribsSizer->Add(xScaleLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 283 m_faceAttribsSizer->Add(m_xScaleEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor1Flags, EditorMargin); 284 m_faceAttribsSizer->Add(yScaleLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 285 m_faceAttribsSizer->Add(m_yScaleEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor2Flags, EditorMargin); 286 ++r; c = 0; 287 288 m_faceAttribsSizer->Add(rotationLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 289 m_faceAttribsSizer->Add(m_rotationEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor1Flags, EditorMargin); 290 m_faceAttribsSizer->Add(m_surfaceValueLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 291 m_faceAttribsSizer->Add(m_surfaceValueEditor, wxGBPosition(r,c++), wxDefaultSpan, Editor2Flags, EditorMargin); 292 ++r; c = 0; 293 294 m_faceAttribsSizer->Add(m_surfaceFlagsLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 295 m_faceAttribsSizer->Add(m_surfaceFlagsEditor, wxGBPosition(r,c++), wxGBSpan(1,3), Editor2Flags, EditorMargin); 296 ++r; c = 0; 297 298 m_faceAttribsSizer->Add(m_contentFlagsLabel, wxGBPosition(r,c++), wxDefaultSpan, LabelFlags, LabelMargin); 299 m_faceAttribsSizer->Add(m_contentFlagsEditor, wxGBPosition(r,c++), wxGBSpan(1,3), Editor2Flags, EditorMargin); 300 ++r; c = 0; 301 302 m_faceAttribsSizer->AddGrowableCol(1); 303 m_faceAttribsSizer->AddGrowableCol(3); 304 m_faceAttribsSizer->SetItemMinSize(m_uvEditor, 100, 100); 305 m_faceAttribsSizer->SetItemMinSize(m_xOffsetEditor, 50, m_xOffsetEditor->GetSize().y); 306 m_faceAttribsSizer->SetItemMinSize(m_yOffsetEditor, 50, m_yOffsetEditor->GetSize().y); 307 m_faceAttribsSizer->SetItemMinSize(m_xScaleEditor, 50, m_xScaleEditor->GetSize().y); 308 m_faceAttribsSizer->SetItemMinSize(m_yScaleEditor, 50, m_yScaleEditor->GetSize().y); 309 m_faceAttribsSizer->SetItemMinSize(m_rotationEditor, 50, m_rotationEditor->GetSize().y); 310 m_faceAttribsSizer->SetItemMinSize(m_surfaceValueEditor, 50, m_rotationEditor->GetSize().y); 311 312 wxSizer* outerSizer = new wxBoxSizer(wxVERTICAL); 313 outerSizer->Add(m_uvEditor, 1, wxEXPAND); 314 outerSizer->Add(new BorderLine(this, BorderLine::Direction_Horizontal), 0, wxEXPAND); 315 outerSizer->AddSpacer(LayoutConstants::WideVMargin); 316 outerSizer->Add(m_faceAttribsSizer, 0, wxEXPAND | wxLEFT | wxRIGHT, LayoutConstants::MediumHMargin); 317 outerSizer->AddSpacer(LayoutConstants::WideVMargin); 318 319 SetSizer(outerSizer); 320 } 321 bindEvents()322 void FaceAttribsEditor::bindEvents() { 323 m_xOffsetEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnXOffsetChanged, this); 324 m_yOffsetEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnYOffsetChanged, this); 325 m_xScaleEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnXScaleChanged, this); 326 m_yScaleEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnYScaleChanged, this); 327 m_rotationEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnRotationChanged, this); 328 m_surfaceValueEditor->Bind(SPIN_CONTROL_EVENT, &FaceAttribsEditor::OnSurfaceValueChanged, this); 329 m_surfaceFlagsEditor->Bind(FLAG_CHANGED_EVENT, &FaceAttribsEditor::OnSurfaceFlagChanged, this); 330 m_contentFlagsEditor->Bind(FLAG_CHANGED_EVENT, &FaceAttribsEditor::OnContentFlagChanged, this); 331 Bind(wxEVT_IDLE, &FaceAttribsEditor::OnIdle, this); 332 } 333 bindObservers()334 void FaceAttribsEditor::bindObservers() { 335 MapDocumentSPtr document = lock(m_document); 336 document->documentWasNewedNotifier.addObserver(this, &FaceAttribsEditor::documentWasNewed); 337 document->documentWasLoadedNotifier.addObserver(this, &FaceAttribsEditor::documentWasLoaded); 338 document->brushFacesDidChangeNotifier.addObserver(this, &FaceAttribsEditor::brushFacesDidChange); 339 document->selectionDidChangeNotifier.addObserver(this, &FaceAttribsEditor::selectionDidChange); 340 document->textureCollectionsDidChangeNotifier.addObserver(this, &FaceAttribsEditor::textureCollectionsDidChange); 341 } 342 unbindObservers()343 void FaceAttribsEditor::unbindObservers() { 344 if (!expired(m_document)) { 345 MapDocumentSPtr document = lock(m_document); 346 document->documentWasNewedNotifier.removeObserver(this, &FaceAttribsEditor::documentWasNewed); 347 document->documentWasLoadedNotifier.removeObserver(this, &FaceAttribsEditor::documentWasLoaded); 348 document->brushFacesDidChangeNotifier.removeObserver(this, &FaceAttribsEditor::brushFacesDidChange); 349 document->selectionDidChangeNotifier.removeObserver(this, &FaceAttribsEditor::selectionDidChange); 350 document->textureCollectionsDidChangeNotifier.removeObserver(this, &FaceAttribsEditor::textureCollectionsDidChange); 351 } 352 } 353 documentWasNewed(MapDocument * document)354 void FaceAttribsEditor::documentWasNewed(MapDocument* document) { 355 m_faces = document->allSelectedBrushFaces(); 356 updateControls(); 357 } 358 documentWasLoaded(MapDocument * document)359 void FaceAttribsEditor::documentWasLoaded(MapDocument* document) { 360 m_faces = document->allSelectedBrushFaces(); 361 updateControls(); 362 } 363 brushFacesDidChange(const Model::BrushFaceList & faces)364 void FaceAttribsEditor::brushFacesDidChange(const Model::BrushFaceList& faces) { 365 MapDocumentSPtr document = lock(m_document); 366 m_faces = document->allSelectedBrushFaces(); 367 updateControls(); 368 } 369 selectionDidChange(const Selection & selection)370 void FaceAttribsEditor::selectionDidChange(const Selection& selection) { 371 MapDocumentSPtr document = lock(m_document); 372 m_faces = document->allSelectedBrushFaces(); 373 updateControls(); 374 } 375 textureCollectionsDidChange()376 void FaceAttribsEditor::textureCollectionsDidChange() { 377 updateControls(); 378 } 379 updateControls()380 void FaceAttribsEditor::updateControls() { 381 if (hasSurfaceAttribs()) { 382 showSurfaceAttribEditors(); 383 wxArrayString surfaceFlagLabels, surfaceFlagTooltips, contentFlagLabels, contentFlagTooltips; 384 getSurfaceFlags(surfaceFlagLabels, surfaceFlagTooltips); 385 getContentFlags(contentFlagLabels, contentFlagTooltips); 386 m_surfaceFlagsEditor->setFlags(surfaceFlagLabels, surfaceFlagTooltips); 387 m_contentFlagsEditor->setFlags(contentFlagLabels, contentFlagTooltips); 388 } else { 389 hideSurfaceAttribEditors(); 390 } 391 392 if (!m_faces.empty()) { 393 bool textureMulti = false; 394 bool xOffsetMulti = false; 395 bool yOffsetMulti = false; 396 bool rotationMulti = false; 397 bool xScaleMulti = false; 398 bool yScaleMulti = false; 399 bool surfaceValueMulti = false; 400 401 Assets::Texture* texture = m_faces[0]->texture(); 402 const float xOffset = m_faces[0]->xOffset(); 403 const float yOffset = m_faces[0]->yOffset(); 404 const float rotation = m_faces[0]->rotation(); 405 const float xScale = m_faces[0]->xScale(); 406 const float yScale = m_faces[0]->yScale(); 407 int setSurfaceFlags = m_faces[0]->surfaceFlags(); 408 int setSurfaceContents = m_faces[0]->surfaceContents(); 409 int mixedSurfaceFlags = 0; 410 int mixedSurfaceContents = 0; 411 const float surfaceValue = m_faces[0]->surfaceValue(); 412 413 for (size_t i = 1; i < m_faces.size(); i++) { 414 Model::BrushFace* face = m_faces[i]; 415 textureMulti |= (texture != face->texture()); 416 xOffsetMulti |= (xOffset != face->xOffset()); 417 yOffsetMulti |= (yOffset != face->yOffset()); 418 rotationMulti |= (rotation != face->rotation()); 419 xScaleMulti |= (xScale != face->xScale()); 420 yScaleMulti |= (yScale != face->yScale()); 421 surfaceValueMulti |= (surfaceValue != face->surfaceValue()); 422 423 combineFlags(sizeof(int)*8, face->surfaceFlags(), setSurfaceFlags, mixedSurfaceFlags); 424 combineFlags(sizeof(int)*8, face->surfaceContents(), setSurfaceContents, mixedSurfaceContents); 425 } 426 427 m_xOffsetEditor->Enable(); 428 m_yOffsetEditor->Enable(); 429 m_rotationEditor->Enable(); 430 m_xScaleEditor->Enable(); 431 m_yScaleEditor->Enable(); 432 m_surfaceValueEditor->Enable(); 433 m_surfaceFlagsEditor->Enable(); 434 m_contentFlagsEditor->Enable(); 435 436 if (textureMulti) { 437 m_textureName->SetLabel("multi"); 438 m_textureName->SetForegroundColour(*wxLIGHT_GREY); 439 m_textureSize->SetLabel("multi"); 440 m_textureSize->SetForegroundColour(*wxLIGHT_GREY); 441 } else { 442 const String& textureName = m_faces[0]->textureName(); 443 if (textureName == Model::BrushFace::NoTextureName) { 444 m_textureName->SetLabel("none"); 445 m_textureName->SetForegroundColour(*wxLIGHT_GREY); 446 m_textureSize->SetLabel(""); 447 m_textureSize->SetForegroundColour(*wxLIGHT_GREY); 448 } else { 449 if (texture != NULL) { 450 wxString sizeLabel; 451 sizeLabel << texture->width() << "*" << texture->height(); 452 453 m_textureName->SetLabel(textureName); 454 m_textureSize->SetLabel(sizeLabel); 455 m_textureName->SetForegroundColour(GetForegroundColour()); 456 m_textureSize->SetForegroundColour(GetForegroundColour()); 457 } else { 458 m_textureName->SetLabel(textureName + " (not found)"); 459 m_textureName->SetForegroundColour(*wxLIGHT_GREY); 460 m_textureSize->SetForegroundColour(*wxLIGHT_GREY); 461 } 462 } 463 } 464 if (xOffsetMulti) { 465 m_xOffsetEditor->SetHint("multi"); 466 m_xOffsetEditor->SetValue(""); 467 } else { 468 m_xOffsetEditor->SetHint(""); 469 m_xOffsetEditor->SetValue(xOffset); 470 } 471 if (yOffsetMulti) { 472 m_yOffsetEditor->SetHint("multi"); 473 m_yOffsetEditor->SetValue(""); 474 } else { 475 m_yOffsetEditor->SetHint(""); 476 m_yOffsetEditor->SetValue(yOffset); 477 } 478 if (rotationMulti) { 479 m_rotationEditor->SetHint("multi"); 480 m_rotationEditor->SetValue(""); 481 } else { 482 m_rotationEditor->SetHint(""); 483 m_rotationEditor->SetValue(rotation); 484 } 485 if (xScaleMulti){ 486 m_xScaleEditor->SetHint("multi"); 487 m_xScaleEditor->SetValue(""); 488 } else { 489 m_xScaleEditor->SetHint(""); 490 m_xScaleEditor->SetValue(xScale); 491 } 492 if (yScaleMulti) { 493 m_yScaleEditor->SetHint("multi"); 494 m_yScaleEditor->SetValue(""); 495 } else { 496 m_yScaleEditor->SetHint(""); 497 m_yScaleEditor->SetValue(yScale); 498 } 499 if (surfaceValueMulti) { 500 m_surfaceValueEditor->SetHint("multi"); 501 m_surfaceValueEditor->SetValue(""); 502 } else { 503 m_surfaceValueEditor->SetHint(""); 504 m_surfaceValueEditor->SetValue(surfaceValue); 505 } 506 m_surfaceFlagsEditor->setFlagValue(setSurfaceFlags, mixedSurfaceFlags); 507 m_contentFlagsEditor->setFlagValue(setSurfaceContents, mixedSurfaceContents); 508 } else { 509 m_xOffsetEditor->SetValue("n/a"); 510 m_xOffsetEditor->Disable(); 511 m_yOffsetEditor->SetValue("n/a"); 512 m_yOffsetEditor->Disable(); 513 m_xScaleEditor->SetValue("n/a"); 514 m_xScaleEditor->Disable(); 515 m_yScaleEditor->SetValue("n/a"); 516 m_yScaleEditor->Disable(); 517 m_rotationEditor->SetValue("n/a"); 518 m_rotationEditor->Disable(); 519 m_surfaceValueEditor->SetValue("n/a"); 520 m_surfaceValueEditor->Disable(); 521 // m_textureView->setTexture(NULL); 522 m_surfaceFlagsEditor->Disable(); 523 m_contentFlagsEditor->Disable(); 524 } 525 } 526 527 hasSurfaceAttribs() const528 bool FaceAttribsEditor::hasSurfaceAttribs() const { 529 MapDocumentSPtr document = lock(m_document); 530 const Model::GamePtr game = document->game(); 531 const Model::GameConfig::FlagsConfig& surfaceFlags = game->surfaceFlags(); 532 const Model::GameConfig::FlagsConfig& contentFlags = game->contentFlags(); 533 534 return !surfaceFlags.flags.empty() && !contentFlags.flags.empty(); 535 } 536 showSurfaceAttribEditors()537 void FaceAttribsEditor::showSurfaceAttribEditors() { 538 m_faceAttribsSizer->Show(m_surfaceValueLabel); 539 m_faceAttribsSizer->Show(m_surfaceValueEditor); 540 m_faceAttribsSizer->Show(m_surfaceFlagsLabel); 541 m_faceAttribsSizer->Show(m_surfaceFlagsEditor); 542 m_faceAttribsSizer->Show(m_contentFlagsLabel); 543 m_faceAttribsSizer->Show(m_contentFlagsEditor); 544 GetParent()->Layout(); 545 } 546 hideSurfaceAttribEditors()547 void FaceAttribsEditor::hideSurfaceAttribEditors() { 548 m_faceAttribsSizer->Hide(m_surfaceValueLabel); 549 m_faceAttribsSizer->Hide(m_surfaceValueEditor); 550 m_faceAttribsSizer->Hide(m_surfaceFlagsLabel); 551 m_faceAttribsSizer->Hide(m_surfaceFlagsEditor); 552 m_faceAttribsSizer->Hide(m_contentFlagsLabel); 553 m_faceAttribsSizer->Hide(m_contentFlagsEditor); 554 GetParent()->Layout(); 555 } 556 557 void getFlags(const Model::GameConfig::FlagConfigList& flags, wxArrayString& names, wxArrayString& descriptions); getFlags(const Model::GameConfig::FlagConfigList & flags,wxArrayString & names,wxArrayString & descriptions)558 void getFlags(const Model::GameConfig::FlagConfigList& flags, wxArrayString& names, wxArrayString& descriptions) { 559 Model::GameConfig::FlagConfigList::const_iterator it, end; 560 for (it = flags.begin(), end = flags.end(); it != end; ++it) { 561 const Model::GameConfig::FlagConfig& flag = *it; 562 names.push_back(flag.name); 563 descriptions.push_back(flag.description); 564 } 565 } 566 getSurfaceFlags(wxArrayString & names,wxArrayString & descriptions) const567 void FaceAttribsEditor::getSurfaceFlags(wxArrayString& names, wxArrayString& descriptions) const { 568 MapDocumentSPtr document = lock(m_document); 569 const Model::GamePtr game = document->game(); 570 const Model::GameConfig::FlagsConfig& surfaceFlags = game->surfaceFlags(); 571 getFlags(surfaceFlags.flags, names, descriptions); 572 } 573 getContentFlags(wxArrayString & names,wxArrayString & descriptions) const574 void FaceAttribsEditor::getContentFlags(wxArrayString& names, wxArrayString& descriptions) const { 575 MapDocumentSPtr document = lock(m_document); 576 const Model::GamePtr game = document->game(); 577 const Model::GameConfig::FlagsConfig& contentFlags = game->contentFlags(); 578 getFlags(contentFlags.flags, names, descriptions); 579 } 580 } 581 } 582