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