Skip to content

Commit d064a2a

Browse files
authored
Merge pull request #51 from klaussilveira/feat/material-picker
Added thumbnail grid view to material browser
2 parents b089adb + 86af9ce commit d064a2a

11 files changed

Lines changed: 437 additions & 12 deletions

libs/wxutil/dataview/ResourceTreeViewToolbar.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ void ResourceTreeViewToolbar::ClearFilter()
122122
{
123123
_treeView->SetFilterText("");
124124
}
125+
126+
_signalFilterTextChanged.emit("");
127+
}
128+
129+
std::string ResourceTreeViewToolbar::GetFilterText() const
130+
{
131+
return _filterEntry->GetValue().ToStdString();
132+
}
133+
134+
sigc::signal<void(const std::string&)>& ResourceTreeViewToolbar::signal_filterTextChanged()
135+
{
136+
return _signalFilterTextChanged;
125137
}
126138

127139
void ResourceTreeViewToolbar::JumpToNextFilterMatch()
@@ -238,6 +250,8 @@ void ResourceTreeViewToolbar::_onFilterTimeoutReached(wxTimerEvent& ev)
238250
}
239251

240252
_filterEntry->Refresh();
253+
254+
_signalFilterTextChanged.emit(filterText.ToStdString());
241255
}
242256

243257
}

libs/wxutil/dataview/ResourceTreeViewToolbar.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <wx/radiobut.h>
55
#include <wx/bmpbuttn.h>
66
#include <wx/timer.h>
7+
#include <sigc++/signal.h>
78

89
#include "ResourceTreeView.h"
910

@@ -32,6 +33,8 @@ class ResourceTreeViewToolbar :
3233

3334
wxTimer _applyFilterTimer;
3435

36+
sigc::signal<void(const std::string&)> _signalFilterTextChanged;
37+
3538
public:
3639
ResourceTreeViewToolbar(wxWindow* parent, ResourceTreeView* treeView = nullptr);
3740

@@ -47,6 +50,12 @@ class ResourceTreeViewToolbar :
4750

4851
void ClearFilter();
4952

53+
// Returns the current filter text
54+
std::string GetFilterText() const;
55+
56+
// Signal emitted when the filter text changes
57+
sigc::signal<void(const std::string&)>& signal_filterTextChanged();
58+
5059
private:
5160
void JumpToNextFilterMatch();
5261
void JumpToPrevFilterMatch();

libs/wxutil/decl/DeclarationSelector.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ DeclarationTreeView* DeclarationSelector::GetTreeView() const
144144
return _treeView;
145145
}
146146

147+
wxPanel* DeclarationSelector::GetLeftPanel() const
148+
{
149+
return _leftPanel;
150+
}
151+
152+
wxSizer* DeclarationSelector::GetTreeViewSizer() const
153+
{
154+
return _treeVbox;
155+
}
156+
147157
const DeclarationTreeView::Columns& DeclarationSelector::GetColumns() const
148158
{
149159
return _columns;
@@ -164,6 +174,23 @@ void DeclarationSelector::PopulateTreeView(const IResourceTreePopulator::Ptr& po
164174
_treeView->Populate(populator);
165175
}
166176

177+
void DeclarationSelector::UpdatePreviewsWithDeclaration(const std::string& declName)
178+
{
179+
for (auto preview : _previews)
180+
{
181+
preview->SetPreviewDeclName(declName);
182+
}
183+
184+
if (!declName.empty())
185+
{
186+
_declFileInfo->SetDeclarationName(declName);
187+
}
188+
else
189+
{
190+
_declFileInfo->Clear();
191+
}
192+
}
193+
167194
const DeclarationTreeView::Columns& DeclarationSelector::CreateDefaultColumns()
168195
{
169196
static DeclarationTreeView::Columns _treeViewColumns;

libs/wxutil/decl/DeclarationSelector.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ class DeclarationSelector :
8383
protected:
8484
DeclarationTreeView* GetTreeView() const;
8585

86+
// Returns the left panel containing the tree view
87+
wxPanel* GetLeftPanel() const;
88+
89+
// Returns the sizer containing the tree view (for adding widgets alongside tree view)
90+
wxSizer* GetTreeViewSizer() const;
91+
8692
// Adds a preview widget to the right of the tree view
8793
void AddPreviewToRightPane(ui::IDeclarationPreview* preview, int sizerProportion = 1);
8894
void AddPreviewToBottom(ui::IDeclarationPreview* preview, int sizerProportion = 0);
@@ -93,6 +99,9 @@ class DeclarationSelector :
9399

94100
void PopulateTreeView(const IResourceTreePopulator::Ptr& populator);
95101

102+
// Manually update all preview widgets with the given declaration name
103+
void UpdatePreviewsWithDeclaration(const std::string& declName);
104+
96105
// Event method invoked when the tree view selection has been changed
97106
virtual void onTreeViewSelectionChanged()
98107
{}

radiant/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ add_executable(darkradiant
103103
ui/materials/MaterialChooser.cpp
104104
ui/materials/MaterialPopulator.cpp
105105
ui/materials/MaterialSelector.cpp
106+
ui/materials/MaterialThumbnailBrowser.cpp
106107
ui/materials/MaterialTreeView.cpp
107108
ui/merge/MapMergePanel.cpp
108109
ui/animationpreview/AnimationPreview.cpp

radiant/ui/materials/MaterialSelector.cpp

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@
88
#include "texturelib.h"
99
#include "gamelib.h"
1010
#include "string/predicate.h"
11+
#include "registry/registry.h"
1112

1213
#include "../common/TexturePreviewCombo.h"
14+
#include "MaterialThumbnailBrowser.h"
1315
#include "wxutil/dataview/VFSTreePopulator.h"
1416
#include "wxutil/dataview/ThreadedDeclarationTreePopulator.h"
17+
#include "wxutil/dataview/ResourceTreeViewToolbar.h"
18+
#include "wxutil/Bitmap.h"
19+
20+
#include <wx/tglbtn.h>
21+
#include <wx/sizer.h>
1522

1623
namespace ui
1724
{
@@ -21,6 +28,7 @@ namespace ui
2128
namespace
2229
{
2330
constexpr const char* const TEXTURE_ICON = "icon_texture.png";
31+
constexpr const char* const RKEY_MATERIAL_SELECTOR_VIEW_MODE = "user/ui/materialSelector/viewMode";
2432
}
2533

2634
/**
@@ -93,26 +101,189 @@ class ThreadedMaterialLoader final :
93101

94102
MaterialSelector::MaterialSelector(wxWindow* parent, TextureFilter textureFilter)
95103
: DeclarationSelector(parent, decl::Type::Material),
96-
_textureFilter(textureFilter)
104+
_textureFilter(textureFilter),
105+
_thumbnailBrowser(nullptr),
106+
_viewToggleBtn(nullptr),
107+
_showingThumbnails(false)
97108
{
109+
createThumbnailBrowser();
110+
createViewToggleButton();
111+
connectFilterSignal();
112+
98113
AddPreviewToBottom(new TexturePreviewCombo(this));
99114

115+
std::string savedMode = GlobalRegistry().get(RKEY_MATERIAL_SELECTOR_VIEW_MODE);
116+
if (savedMode == "thumbnails")
117+
{
118+
_showingThumbnails = true;
119+
_viewToggleBtn->SetValue(true);
120+
switchView(true);
121+
}
122+
100123
Populate();
101124
}
102125

126+
MaterialSelector::~MaterialSelector()
127+
{
128+
GlobalRegistry().set(RKEY_MATERIAL_SELECTOR_VIEW_MODE,
129+
_showingThumbnails ? "thumbnails" : "tree");
130+
131+
_thumbnailSelectionConn.disconnect();
132+
_thumbnailActivatedConn.disconnect();
133+
_filterTextChangedConn.disconnect();
134+
}
135+
136+
void MaterialSelector::createThumbnailBrowser()
137+
{
138+
MaterialThumbnailBrowser::TextureFilter thumbnailFilter;
139+
switch (_textureFilter)
140+
{
141+
case TextureFilter::Lights:
142+
thumbnailFilter = MaterialThumbnailBrowser::TextureFilter::Lights;
143+
break;
144+
case TextureFilter::Regular:
145+
thumbnailFilter = MaterialThumbnailBrowser::TextureFilter::Regular;
146+
break;
147+
case TextureFilter::All:
148+
default:
149+
thumbnailFilter = MaterialThumbnailBrowser::TextureFilter::All;
150+
break;
151+
}
152+
153+
_thumbnailBrowser = new MaterialThumbnailBrowser(GetLeftPanel(), thumbnailFilter);
154+
_thumbnailBrowser->Hide();
155+
156+
GetTreeViewSizer()->Insert(2, _thumbnailBrowser, 1, wxEXPAND);
157+
158+
_thumbnailSelectionConn = _thumbnailBrowser->signal_selectionChanged().connect(
159+
sigc::mem_fun(this, &MaterialSelector::onThumbnailSelectionChanged));
160+
_thumbnailActivatedConn = _thumbnailBrowser->signal_itemActivated().connect(
161+
sigc::mem_fun(this, &MaterialSelector::onThumbnailItemActivated));
162+
}
163+
164+
void MaterialSelector::createViewToggleButton()
165+
{
166+
auto* sizer = GetTreeViewSizer();
167+
if (sizer->GetItemCount() > 0)
168+
{
169+
auto* toolbarItem = sizer->GetItem(static_cast<size_t>(0));
170+
if (toolbarItem && toolbarItem->GetWindow())
171+
{
172+
auto* toolbar = dynamic_cast<wxutil::ResourceTreeViewToolbar*>(toolbarItem->GetWindow());
173+
if (toolbar)
174+
{
175+
_viewToggleBtn = new wxBitmapToggleButton(toolbar, wxID_ANY,
176+
wxutil::GetLocalBitmap("bgimage16.png"));
177+
_viewToggleBtn->SetToolTip(_("Toggle between tree view and thumbnail grid view"));
178+
toolbar->GetRightSizer()->Add(_viewToggleBtn, wxSizerFlags().Border(wxLEFT, 6));
179+
_viewToggleBtn->Bind(wxEVT_TOGGLEBUTTON, &MaterialSelector::onViewToggle, this);
180+
}
181+
}
182+
}
183+
}
184+
185+
void MaterialSelector::connectFilterSignal()
186+
{
187+
auto* sizer = GetTreeViewSizer();
188+
if (sizer->GetItemCount() > 0)
189+
{
190+
auto* toolbarItem = sizer->GetItem(static_cast<size_t>(0));
191+
if (toolbarItem && toolbarItem->GetWindow())
192+
{
193+
auto* toolbar = dynamic_cast<wxutil::ResourceTreeViewToolbar*>(toolbarItem->GetWindow());
194+
if (toolbar)
195+
{
196+
_filterTextChangedConn = toolbar->signal_filterTextChanged().connect(
197+
sigc::mem_fun(this, &MaterialSelector::onFilterTextChanged));
198+
}
199+
}
200+
}
201+
}
202+
203+
void MaterialSelector::onFilterTextChanged(const std::string& filterText)
204+
{
205+
if (_thumbnailBrowser)
206+
{
207+
_thumbnailBrowser->setExternalFilterText(filterText);
208+
}
209+
}
210+
211+
void MaterialSelector::switchView(bool showThumbnails)
212+
{
213+
if (showThumbnails)
214+
{
215+
_thumbnailBrowser->setSelectedShader(DeclarationSelector::GetSelectedDeclName());
216+
GetTreeView()->Hide();
217+
_thumbnailBrowser->Show();
218+
_thumbnailBrowser->queueUpdate();
219+
}
220+
else
221+
{
222+
std::string selectedShader = _thumbnailBrowser->getSelectedShader();
223+
if (!selectedShader.empty())
224+
{
225+
SetSelectedDeclName(selectedShader);
226+
}
227+
_thumbnailBrowser->Hide();
228+
GetTreeView()->Show();
229+
}
230+
231+
_showingThumbnails = showThumbnails;
232+
GetLeftPanel()->Layout();
233+
}
234+
235+
void MaterialSelector::onViewToggle(wxCommandEvent& ev)
236+
{
237+
switchView(ev.IsChecked());
238+
}
239+
240+
void MaterialSelector::onThumbnailSelectionChanged()
241+
{
242+
UpdatePreviewsWithDeclaration(_thumbnailBrowser->getSelectedShader());
243+
_selectionChanged();
244+
}
245+
246+
void MaterialSelector::onThumbnailItemActivated()
247+
{
248+
onTreeViewItemActivated();
249+
}
250+
103251
void MaterialSelector::Populate()
104252
{
105253
PopulateTreeView(std::make_shared<ThreadedMaterialLoader>(GetColumns(), _textureFilter));
254+
255+
if (_thumbnailBrowser)
256+
{
257+
_thumbnailBrowser->queueUpdate();
258+
}
259+
}
260+
261+
std::string MaterialSelector::GetSelectedDeclName() const
262+
{
263+
if (_showingThumbnails && _thumbnailBrowser)
264+
{
265+
return _thumbnailBrowser->getSelectedShader();
266+
}
267+
return DeclarationSelector::GetSelectedDeclName();
106268
}
107269

108270
MaterialPtr MaterialSelector::getSelectedShader()
109271
{
110-
return GlobalMaterialManager().getMaterial(GetSelectedDeclName());
272+
return GlobalMaterialManager().getMaterial(GetSelectedDeclName());
111273
}
112274

113275
void MaterialSelector::onTreeViewSelectionChanged()
114276
{
277+
if (!_showingThumbnails && _thumbnailBrowser)
278+
{
279+
_thumbnailBrowser->setSelectedShader(DeclarationSelector::GetSelectedDeclName());
280+
}
115281
_selectionChanged();
116282
}
117283

284+
bool MaterialSelector::onTreeViewItemActivated()
285+
{
286+
return false;
287+
}
288+
118289
} // namespace

0 commit comments

Comments
 (0)