From b1254d7061da7184857cb0644b29d5ac3a43db74 Mon Sep 17 00:00:00 2001 From: codereader Date: Fri, 21 Oct 2022 11:14:45 +0200 Subject: [PATCH] #6131: Convert PatchInspector to a dockable control --- include/ui/iusercontrol.h | 1 + radiant/ui/UserInterfaceModule.cpp | 5 +- radiant/ui/patch/PatchInspector.cpp | 118 ++++++----------------- radiant/ui/patch/PatchInspector.h | 49 +++------- radiant/ui/patch/PatchInspectorControl.h | 35 +++++++ tools/msvc/DarkRadiant.vcxproj | 1 + tools/msvc/DarkRadiant.vcxproj.filters | 3 + 7 files changed, 86 insertions(+), 126 deletions(-) create mode 100644 radiant/ui/patch/PatchInspectorControl.h diff --git a/include/ui/iusercontrol.h b/include/ui/iusercontrol.h index ee2c573a88..e52846aa4f 100644 --- a/include/ui/iusercontrol.h +++ b/include/ui/iusercontrol.h @@ -46,6 +46,7 @@ struct UserControl constexpr static const char* OrthoView = "OrthoView"; constexpr static const char* TextureBrowser = "TextureBrowser"; constexpr static const char* SurfaceInspector = "SurfaceInspector"; + constexpr static const char* PatchInspector = "PatchInspector"; constexpr static const char* LayerControlPanel = "LayerControlPanel"; constexpr static const char* TextureTool = "TextureTool"; }; diff --git a/radiant/ui/UserInterfaceModule.cpp b/radiant/ui/UserInterfaceModule.cpp index f9cd6c701e..fb27be8018 100644 --- a/radiant/ui/UserInterfaceModule.cpp +++ b/radiant/ui/UserInterfaceModule.cpp @@ -75,6 +75,7 @@ #include "console/ConsoleControl.h" #include "layers/LayerControl.h" +#include "patch/PatchInspectorControl.h" #include "surfaceinspector/SurfaceInspectorControl.h" #include "textool/TextureToolControl.h" @@ -253,6 +254,7 @@ void UserInterfaceModule::initialiseModule(const IApplicationContext& ctx) registerControl(std::make_shared()); registerControl(std::make_shared()); registerControl(std::make_shared()); + registerControl(std::make_shared()); GlobalMainFrame().signal_MainFrameConstructed().connect([&]() { @@ -260,6 +262,7 @@ void UserInterfaceModule::initialiseModule(const IApplicationContext& ctx) GlobalMainFrame().addControl(UserControl::SurfaceInspector, { IMainFrame::Location::FloatingWindow, false }); GlobalMainFrame().addControl(UserControl::LayerControlPanel, { IMainFrame::Location::FloatingWindow, false }); GlobalMainFrame().addControl(UserControl::TextureTool, { IMainFrame::Location::FloatingWindow, false }); + GlobalMainFrame().addControl(UserControl::PatchInspector, { IMainFrame::Location::FloatingWindow, false }); }); } @@ -423,8 +426,8 @@ void UserInterfaceModule::registerUICommands() GlobalCommandSystem().addCommand("ToggleLightInspector", LightInspector::toggleInspector); GlobalCommandSystem().addStatement("SurfaceInspector", fmt::format("ToggleControl {0}", UserControl::SurfaceInspector), false); GlobalCommandSystem().addStatement("ToggleLayerControlDialog", fmt::format("ToggleControl {0}", UserControl::LayerControlPanel), false); + GlobalCommandSystem().addStatement("PatchInspector", fmt::format("ToggleControl {0}", UserControl::PatchInspector), false); - GlobalCommandSystem().addCommand("PatchInspector", PatchInspector::toggle); GlobalCommandSystem().addCommand("MergeControlDialog", MergeControlDialog::ShowDialog); GlobalCommandSystem().addCommand("OverlayDialog", OverlayDialog::toggle); GlobalCommandSystem().addCommand("TransformDialog", TransformDialog::toggle); diff --git a/radiant/ui/patch/PatchInspector.cpp b/radiant/ui/patch/PatchInspector.cpp index 3ee75ec7ff..47e17aff2a 100644 --- a/radiant/ui/patch/PatchInspector.cpp +++ b/radiant/ui/patch/PatchInspector.cpp @@ -1,7 +1,6 @@ #include "PatchInspector.h" #include "i18n.h" -#include "itextstream.h" #include "ui/imainframe.h" #include "iundo.h" @@ -11,10 +10,10 @@ #include #include #include -#include "wxutil/Bitmap.h" #include "registry/Widgets.h" #include "selectionlib.h" +#include "wxutil/Bitmap.h" #include "wxutil/ControlButton.h" #include "util/ScopedBoolLock.h" @@ -25,11 +24,9 @@ namespace ui namespace { - const char* const WINDOW_TITLE = N_("Patch Inspector"); - const char* const LABEL_STEP = N_("Step:"); + constexpr const char* const LABEL_STEP = N_("Step:"); const std::string RKEY_ROOT = "user/ui/patch/patchInspector/"; - const std::string RKEY_WINDOW_STATE = RKEY_ROOT + "window"; const std::string RKEY_X_STEP = RKEY_ROOT + "xCoordStep"; const std::string RKEY_Y_STEP = RKEY_ROOT + "yCoordStep"; const std::string RKEY_Z_STEP = RKEY_ROOT + "zCoordStep"; @@ -37,8 +34,8 @@ namespace const std::string RKEY_T_STEP = RKEY_ROOT + "tCoordStep"; } -PatchInspector::PatchInspector() : - TransientWindow(_(WINDOW_TITLE), GlobalMainFrame().getWxTopLevelWindow(), true), +PatchInspector::PatchInspector(wxWindow* parent) : + wxPanel(parent), _rowCombo(nullptr), _colCombo(nullptr), _selectionInfo(GlobalSelectionSystem().getSelectionInfo()), @@ -47,50 +44,22 @@ PatchInspector::PatchInspector() : _updateActive(false), _updateNeeded(false) { - Bind(wxEVT_IDLE, &PatchInspector::onIdle, this); - // Create all the widgets and pack them into the window populateWindow(); - InitialiseWindowPosition(410, 480, RKEY_WINDOW_STATE); -} + _undoHandler.disconnect(); + _redoHandler.disconnect(); -std::shared_ptr& PatchInspector::InstancePtr() -{ - static std::shared_ptr _instancePtr; - return _instancePtr; -} + // Register self to the SelSystem to get notified upon selection changes. + GlobalSelectionSystem().addObserver(this); -void PatchInspector::onMainFrameShuttingDown() -{ - rMessage() << "PatchInspector shutting down." << std::endl; + _undoHandler = GlobalMapModule().signal_postUndo().connect( + sigc::mem_fun(this, &PatchInspector::queueUpdate)); + _redoHandler = GlobalMapModule().signal_postRedo().connect( + sigc::mem_fun(this, &PatchInspector::queueUpdate)); - if (IsShownOnScreen()) - { - Hide(); - } - - // Destroy the window - SendDestroyEvent(); - InstancePtr().reset(); -} - -PatchInspector& PatchInspector::Instance() -{ - auto& instancePtr = InstancePtr(); - - if (!instancePtr) - { - // Not yet instantiated, do it now - instancePtr.reset(new PatchInspector); - - // Pre-destruction cleanup - GlobalMainFrame().signal_MainFrameShuttingDown().connect( - sigc::mem_fun(*instancePtr, &PatchInspector::onMainFrameShuttingDown) - ); - } - - return *instancePtr; + // Check for selection changes + rescanSelection(); } void PatchInspector::populateWindow() @@ -106,8 +75,8 @@ void PatchInspector::populateWindow() _colCombo = findNamedObject(this, "PatchInspectorControlColumn"); // Create the controls table - wxPanel* coordPanel = findNamedObject(this, "PatchInspectorCoordPanel"); - wxFlexGridSizer* table = new wxFlexGridSizer(5, 5, 6, 16); + auto coordPanel = findNamedObject(this, "PatchInspectorCoordPanel"); + auto table = new wxFlexGridSizer(5, 5, 6, 16); table->AddGrowableCol(1); coordPanel->GetSizer()->Add(table, 1, wxEXPAND); @@ -126,24 +95,22 @@ void PatchInspector::populateWindow() registry::bindWidget(_coords["t"].stepEntry, RKEY_T_STEP); // Connect all the arrow buttons - for (CoordMap::iterator i = _coords.begin(); i != _coords.end(); ++i) + for (const auto& [_, row] : _coords) { - CoordRow& row = i->second; - // Pass a CoordRow ref to the callback, that's all it will need to update row.smaller->Bind(wxEVT_BUTTON, std::bind(&PatchInspector::onClickSmaller, this, row)); row.larger->Bind(wxEVT_BUTTON, std::bind(&PatchInspector::onClickLarger, this, row)); } // Tesselation checkbox - findNamedObject(this, "PatchInspectorFixedSubdivisions")->Connect( - wxEVT_CHECKBOX, wxCommandEventHandler(PatchInspector::onFixedTessChange), NULL, this); + findNamedObject(this, "PatchInspectorFixedSubdivisions")->Bind( + wxEVT_CHECKBOX, &PatchInspector::onFixedTessChange, this); // Tesselation values - findNamedObject(this, "PatchInspectorSubdivisionsX")->Connect( - wxEVT_SPINCTRL, wxSpinEventHandler(PatchInspector::onTessChange), NULL, this); - findNamedObject(this, "PatchInspectorSubdivisionsY")->Connect( - wxEVT_SPINCTRL, wxSpinEventHandler(PatchInspector::onTessChange), NULL, this); + findNamedObject(this, "PatchInspectorSubdivisionsX")->Bind( + wxEVT_SPINCTRL, &PatchInspector::onTessChange, this); + findNamedObject(this, "PatchInspectorSubdivisionsY")->Bind( + wxEVT_SPINCTRL, &PatchInspector::onTessChange, this); } PatchInspector::CoordRow PatchInspector::createCoordRow( @@ -191,8 +158,8 @@ PatchInspector::CoordRow PatchInspector::createCoordRow( void PatchInspector::queueUpdate() { - // Request an idle callback to perform the update when GTK is idle _updateNeeded = true; + requestIdleCallback(); } void PatchInspector::update() @@ -246,13 +213,10 @@ void PatchInspector::loadControlVertex() } } -// Pre-hide callback -void PatchInspector::_preHide() +PatchInspector::~PatchInspector() { - TransientWindow::_preHide(); - // Clear the patch, we don't need to observe it while hidden - setPatch(IPatchNodePtr()); + setPatch({}); // A hidden PatchInspector doesn't need to listen for events _undoHandler.disconnect(); @@ -261,26 +225,6 @@ void PatchInspector::_preHide() GlobalSelectionSystem().removeObserver(this); } -// Pre-show callback -void PatchInspector::_preShow() -{ - TransientWindow::_preShow(); - - _undoHandler.disconnect(); - _redoHandler.disconnect(); - - // Register self to the SelSystem to get notified upon selection changes. - GlobalSelectionSystem().addObserver(this); - - _undoHandler = GlobalMapModule().signal_postUndo().connect( - sigc::mem_fun(this, &PatchInspector::queueUpdate)); - _redoHandler = GlobalMapModule().signal_postRedo().connect( - sigc::mem_fun(this, &PatchInspector::queueUpdate)); - - // Check for selection changes before showing the dialog again - rescanSelection(); -} - void PatchInspector::selectionChanged(const scene::INodePtr& node, bool isComponent) { if (!isComponent) @@ -541,12 +485,6 @@ void PatchInspector::onClickSmaller(CoordRow& row) row.value->SetValue(string::to_string(value - step)); } -// static command target -void PatchInspector::toggle(const cmd::ArgumentList& args) -{ - Instance().ToggleVisibility(); -} - void PatchInspector::onPatchControlPointsChanged() { queueUpdate(); @@ -562,7 +500,7 @@ void PatchInspector::onPatchDestruction() rescanSelection(); } -void PatchInspector::onIdle(wxIdleEvent& ev) +void PatchInspector::onIdle() { if (_updateNeeded) { @@ -570,4 +508,4 @@ void PatchInspector::onIdle(wxIdleEvent& ev) } } -} // namespace ui +} // namespace diff --git a/radiant/ui/patch/PatchInspector.h b/radiant/ui/patch/PatchInspector.h index c75092e62c..6f87da6518 100644 --- a/radiant/ui/patch/PatchInspector.h +++ b/radiant/ui/patch/PatchInspector.h @@ -1,21 +1,18 @@ #pragma once #include -#include "icommandsystem.h" #include "iselection.h" -#include "iradiant.h" #include "ipatch.h" #include #include -#include "wxutil/window/TransientWindow.h" +#include #include "wxutil/event/SingleIdleCallback.h" #include "wxutil/XmlResourceBasedWidget.h" namespace wxutil { class ControlButton; } class wxChoice; -class wxPanel; class wxTextCtrl; class wxSizer; @@ -23,11 +20,12 @@ namespace ui { class PatchInspector : - public wxutil::TransientWindow, + public wxPanel, public selection::SelectionSystem::Observer, public IPatch::Observer, private wxutil::XmlResourceBasedWidget, - public sigc::trackable + public sigc::trackable, + public wxutil::SingleIdleCallback { private: wxChoice* _rowCombo; @@ -94,7 +92,6 @@ class PatchInspector : // Gets called if the spin buttons with the coordinates get changed void onCoordChange(wxCommandEvent& ev); - void onStepChanged(); void onClickSmaller(CoordRow& row); void onClickLarger(CoordRow& row); @@ -104,36 +101,25 @@ class PatchInspector : void onTessChange(wxSpinEvent& ev); public: - PatchInspector(); - - /** greebo: Contains the static instance of this dialog. - * Constructs the instance and calls toggle() when invoked. - */ - static PatchInspector& Instance(); - - // The command target - static void toggle(const cmd::ArgumentList& args); + PatchInspector(wxWindow* parent); + ~PatchInspector() override; /** greebo: SelectionSystem::Observer implementation. Gets called by * the SelectionSystem upon selection change to allow updating of the * patch property widgets. */ - void selectionChanged(const scene::INodePtr& node, bool isComponent); + void selectionChanged(const scene::INodePtr& node, bool isComponent) override; // Request a deferred update of the UI elements (is performed when GTK is idle) void queueUpdate(); - /** - * greebo: Safely disconnects this dialog from all systems - * (SelectionSystem, EventManager, ...) - * Also saves the window state to the registry. - */ - void onMainFrameShuttingDown(); - // Patch::Observer - void onPatchControlPointsChanged(); - void onPatchTextureChanged(); - void onPatchDestruction(); + void onPatchControlPointsChanged() override; + void onPatchTextureChanged() override; + void onPatchDestruction() override; + +protected: + void onIdle() override; private: void setPatch(const IPatchNodePtr& patch); @@ -146,13 +132,6 @@ class PatchInspector : // Populates the combo boxes void repopulateVertexChooser(); - - // This is where the static shared_ptr of the singleton instance is held. - static std::shared_ptr& InstancePtr(); - - // Called by wxWidgets when the system is idle - void onIdle(wxIdleEvent& ev); - -}; // class PatchInspector +}; } // namespace ui diff --git a/radiant/ui/patch/PatchInspectorControl.h b/radiant/ui/patch/PatchInspectorControl.h new file mode 100644 index 0000000000..b60075efc8 --- /dev/null +++ b/radiant/ui/patch/PatchInspectorControl.h @@ -0,0 +1,35 @@ +#pragma once + +#include "i18n.h" +#include "ui/iusercontrol.h" +#include "PatchInspector.h" + +namespace ui +{ + +class PatchInspectorControl : + public IUserControl +{ +public: + std::string getControlName() override + { + return UserControl::PatchInspector; + } + + std::string getDisplayName() override + { + return _("Patch Inspector"); + } + + std::string getIcon() override + { + return {}; + } + + wxWindow* createWidget(wxWindow* parent) override + { + return new PatchInspector(parent); + } +}; + +} diff --git a/tools/msvc/DarkRadiant.vcxproj b/tools/msvc/DarkRadiant.vcxproj index ba949f8baf..e34383df98 100644 --- a/tools/msvc/DarkRadiant.vcxproj +++ b/tools/msvc/DarkRadiant.vcxproj @@ -555,6 +555,7 @@ + diff --git a/tools/msvc/DarkRadiant.vcxproj.filters b/tools/msvc/DarkRadiant.vcxproj.filters index 4474add88e..194ba1a91d 100644 --- a/tools/msvc/DarkRadiant.vcxproj.filters +++ b/tools/msvc/DarkRadiant.vcxproj.filters @@ -1416,6 +1416,9 @@ src\textool + + src\ui\patch +