diff --git a/install/user.xml b/install/user.xml index 8b7a00ce25..55c1635f0f 100644 --- a/install/user.xml +++ b/install/user.xml @@ -340,6 +340,7 @@ + diff --git a/libs/wxutil/preview/SkinPreview.h b/libs/wxutil/preview/SkinPreview.h new file mode 100644 index 0000000000..a0bebabf0e --- /dev/null +++ b/libs/wxutil/preview/SkinPreview.h @@ -0,0 +1,41 @@ +#pragma once + +#include "ui/ideclpreview.h" +#include "ModelPreview.h" + +namespace wxutil +{ + +class SkinPreview : + public ModelPreview, + public ui::IDeclarationPreview +{ +private: + std::string _model; + +public: + SkinPreview(wxWindow* parent, const std::string& model) : + ModelPreview(parent), + _model(model) + {} + + // Returns the widget that can be packed into the selector container + wxWindow* GetPreviewWidget() override + { + return _mainPanel; + } + + void ClearPreview() override + { + setModel({}); + setSkin({}); + } + + void SetPreviewDeclName(const std::string& declName) override + { + setModel(_model); + setSkin(declName); + } +}; + +} diff --git a/radiant/ui/common/SkinChooser.cpp b/radiant/ui/common/SkinChooser.cpp index 0e644e267a..d11292d734 100644 --- a/radiant/ui/common/SkinChooser.cpp +++ b/radiant/ui/common/SkinChooser.cpp @@ -9,9 +9,10 @@ #include "ifavourites.h" #include "debugging/ScopedDebugTimer.h" #include "wxutil/dataview/ThreadedDeclarationTreePopulator.h" -#include "wxutil/dataview/TreeView.h" #include "wxutil/dataview/VFSTreePopulator.h" #include "wxutil/decl/DeclarationSelector.h" +#include "wxutil/preview/SkinPreview.h" +#include "ui/modelselector/MaterialsList.h" namespace ui { @@ -127,21 +128,42 @@ class SkinSelector : public wxutil::DeclarationSelector { private: + std::string _model; + wxDataViewItem _allSkinsItem; wxDataViewItem _matchingSkinsItem; + std::unique_ptr _preview; + MaterialsList* _materialsList; + public: - SkinSelector(wxWindow* parent) : - DeclarationSelector(parent, decl::Type::Skin) + SkinSelector(wxWindow* parent, const std::string& model) : + DeclarationSelector(parent, decl::Type::Skin), + _model(model), + _preview(new wxutil::SkinPreview(this, _model)), + _materialsList(new MaterialsList(this, _preview->getRenderSystem())) { // We want to control ourselves which items are expanded after population GetTreeView()->SetExpandTopLevelItemsAfterPopulation(false); GetTreeView()->Bind(wxutil::EV_TREEVIEW_POPULATION_FINISHED, &SkinSelector::onTreeViewPopulationFinished, this); + + //AddPreviewToBottom(_materialsList); // TODO + AddPreviewToRightPane(_preview.get()); + + // Models are lazy-loaded, subscribe to the preview's event + _preview->signal_ModelLoaded().connect(sigc::mem_fun(this, &SkinSelector::onPreviewModelLoaded)); + + _materialsList->SetMinClientSize(wxSize(-1, 140)); + + // Refresh preview when material visibility changed + _materialsList->signal_visibilityChanged().connect( + sigc::mem_fun(*_preview, &wxutil::ModelPreview::queueDraw) + ); } - void Populate(const std::string& model) + void Populate() { - PopulateTreeView(std::make_shared(GetColumns(), model, _allSkinsItem, _matchingSkinsItem)); + PopulateTreeView(std::make_shared(GetColumns(), _model, _allSkinsItem, _matchingSkinsItem)); } void SetSelectedDeclName(const std::string& skin) override @@ -167,6 +189,25 @@ class SkinSelector : } private: + void onPreviewModelLoaded(const model::ModelNodePtr& model) + { + updateMaterialsList(); + } + + void updateMaterialsList() + { + // Update the material list + auto modelNode = Node_getModel(_preview->getModelNode()); + + if (!modelNode) + { + _materialsList->clear(); + return; + } + + _materialsList->updateFromModel(modelNode->getIModel()); + } + void onTreeViewPopulationFinished(wxutil::ResourceTreeView::PopulationFinishedEvent& ev) { // Make sure the "matching skins" item is expanded @@ -175,10 +216,10 @@ class SkinSelector : } }; -SkinChooser::SkinChooser() : - DialogBase(_(WINDOW_TITLE)), - _selector(nullptr), - _materialsList(nullptr) +SkinChooser::SkinChooser(const std::string& model) : + DialogBase(_(WINDOW_TITLE), "SkinChooser"), + _model(model), + _selector(nullptr) { populateWindow(); } @@ -190,7 +231,7 @@ void SkinChooser::populateWindow() wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL); GetSizer()->Add(vbox, 1, wxEXPAND | wxALL, 12); - _selector = new SkinSelector(this); + _selector = new SkinSelector(this, _model); #if 0 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, @@ -215,14 +256,7 @@ void SkinChooser::populateWindow() _treeView->Bind(wxutil::EV_TREEVIEW_POPULATION_FINISHED, &SkinChooser::_onTreeViewPopulationFinished, this); _treeViewToolbar = new wxutil::ResourceTreeViewToolbar(leftPanel, _treeView); -#endif - // Preview - _preview.reset(new wxutil::ModelPreview(this)); - _preview->getWidget()->SetMinClientSize(wxSize(GetSize().GetWidth() / 3, -1)); - _materialsList = new MaterialsList(this, _preview->getRenderSystem()); - _materialsList->SetMinClientSize(wxSize(-1, 140)); -#if 0 // Refresh preview when material visibility changed _materialsList->signal_visibilityChanged().connect( sigc::mem_fun(*_preview, &wxutil::ModelPreview::queueDraw) @@ -237,10 +271,6 @@ void SkinChooser::populateWindow() // Pack treeview and preview splitter->SplitVertically(leftPanel, _preview->getWidget()); -#endif - FitToScreen(0.8f, 0.8f); - -#if 0 // Set the default size of the window splitter->SetSashPosition(static_cast(GetSize().GetWidth() * 0.3f)); @@ -251,6 +281,8 @@ void SkinChooser::populateWindow() vbox->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_RIGHT | wxTOP, 12); Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED, &SkinChooser::_onItemActivated, this ); + + RegisterPersistableObject(_selector); } int SkinChooser::ShowModal() @@ -260,11 +292,6 @@ int SkinChooser::ShowModal() // Display the model in the window title SetTitle(std::string(_(WINDOW_TITLE)) + ": " + _model); - // Models are lazy-loaded, subscribe to the preview's event - _modelLoadedConn.disconnect(); - _modelLoadedConn = _preview->signal_ModelLoaded().connect( - sigc::mem_fun(this, &SkinChooser::_onPreviewModelLoaded)); - int returnCode = DialogBase::ShowModal(); if (returnCode == wxID_OK) @@ -278,9 +305,6 @@ int SkinChooser::ShowModal() _lastSkin = _prevSkin; } - _modelLoadedConn.disconnect(); - _preview->setModel(""); // release model - return returnCode; } @@ -293,7 +317,7 @@ void SkinChooser::_onItemActivated(wxDataViewEvent& ev) // Populate the list of skins void SkinChooser::populateSkins() { - _selector->Populate(_model); + _selector->Populate(); } std::string SkinChooser::getSelectedSkin() @@ -304,15 +328,13 @@ std::string SkinChooser::getSelectedSkin() void SkinChooser::setSelectedSkin(const std::string& skin) { _selector->SetSelectedDeclName(skin); - - handleSelectionChange(); } // Static method to display singleton instance and choose a skin std::string SkinChooser::chooseSkin(const std::string& model, const std::string& prev) { - auto dialog = new SkinChooser(); + auto dialog = new SkinChooser(model); dialog->_model = model; dialog->_prevSkin = prev; @@ -326,41 +348,6 @@ std::string SkinChooser::chooseSkin(const std::string& model, return selectedSkin; } -void SkinChooser::handleSelectionChange() -{ - auto selectedSkin = getSelectedSkin(); - - // Set the model preview to show the model with the selected skin - _preview->setModel(_model); - _preview->setSkin(selectedSkin); - - updateMaterialsList(); -} - -void SkinChooser::updateMaterialsList() -{ - // Update the material list - auto modelNode = Node_getModel(_preview->getModelNode()); - - if (!modelNode) - { - _materialsList->clear(); - return; - } - - _materialsList->updateFromModel(modelNode->getIModel()); -} - -void SkinChooser::_onPreviewModelLoaded(const model::ModelNodePtr& model) -{ - updateMaterialsList(); -} - -void SkinChooser::_onSelChanged(wxDataViewEvent& ev) -{ - handleSelectionChange(); -} - void SkinChooser::_onTreeViewPopulationFinished(wxutil::ResourceTreeView::PopulationFinishedEvent& ev) { // Select the active skin diff --git a/radiant/ui/common/SkinChooser.h b/radiant/ui/common/SkinChooser.h index 32ebde96cf..fc3a15e666 100644 --- a/radiant/ui/common/SkinChooser.h +++ b/radiant/ui/common/SkinChooser.h @@ -4,10 +4,8 @@ #include "imodel.h" #include "wxutil/dialog/DialogBase.h" -#include "wxutil/preview/ModelPreview.h" #include -#include "ui/modelselector/MaterialsList.h" #include "wxutil/dataview/ResourceTreeView.h" namespace ui @@ -23,24 +21,18 @@ class SkinChooser : public wxutil::DialogBase { private: - SkinSelector* _selector; - MaterialsList* _materialsList; - // The model name to use for skin matching std::string _model; + SkinSelector* _selector; + // The last skin selected, and the original (previous) skin std::string _lastSkin; std::string _prevSkin; - // Model preview widget - wxutil::ModelPreviewPtr _preview; - - sigc::connection _modelLoadedConn; - private: // Constructor creates widgets - SkinChooser(); + SkinChooser(const std::string& model); // Widget creation functions void populateWindow(); @@ -49,23 +41,16 @@ class SkinChooser : void populateSkins(); // callbacks - void _onSelChanged(wxDataViewEvent& ev); void _onTreeViewPopulationFinished(wxutil::ResourceTreeView::PopulationFinishedEvent& ev); // Retrieve the currently selected skin std::string getSelectedSkin(); void setSelectedSkin(const std::string& skin); - void handleSelectionChange(); - void updateMaterialsList(); - void _onItemActivated( wxDataViewEvent& ev ); - void _onPreviewModelLoaded(const model::ModelNodePtr& model); public: - - // Override Dialogbase - int ShowModal(); + int ShowModal() override; /** Display the dialog and return the skin chosen by the user, or an empty * string if no selection was made. This static method enters are recursive diff --git a/tools/msvc/wxutillib.vcxproj b/tools/msvc/wxutillib.vcxproj index f36439e69a..5ece6d20e2 100644 --- a/tools/msvc/wxutillib.vcxproj +++ b/tools/msvc/wxutillib.vcxproj @@ -192,6 +192,7 @@ + diff --git a/tools/msvc/wxutillib.vcxproj.filters b/tools/msvc/wxutillib.vcxproj.filters index 5682e2414f..efef302435 100644 --- a/tools/msvc/wxutillib.vcxproj.filters +++ b/tools/msvc/wxutillib.vcxproj.filters @@ -182,6 +182,9 @@ preview + + preview +