From 6218928e152f83747856102e65fc6095f1a2e055 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sun, 23 Mar 2025 15:31:00 -0400 Subject: [PATCH] Refresh object details without reloading widget. + Clean up ToolBox widget tree. --- src/designer-plugins/toolbox.cpp | 192 +++++++++++++------------------ src/designer-plugins/toolbox.h | 67 +++++++---- 2 files changed, 121 insertions(+), 138 deletions(-) diff --git a/src/designer-plugins/toolbox.cpp b/src/designer-plugins/toolbox.cpp index a670907..909bdf1 100644 --- a/src/designer-plugins/toolbox.cpp +++ b/src/designer-plugins/toolbox.cpp @@ -17,20 +17,53 @@ using namespace Qtk; ToolBox::ToolBox(QWidget * parent) : - QDockWidget(parent), objectDetails_(this), ui(new Ui::ToolBox) + QDockWidget(parent), objectDetails_(this), + transformPanel_(this, "Transform:"), scalePanel_(this, "Scale:"), + vertex_(this, "Vertex Shader:"), fragment_(this, "Fragment Shader:"), + properiesForm_(new QFormLayout), shaderForm_(new QFormLayout), + ui(new Ui::ToolBox) { ui->setupUi(this); setMinimumWidth(350); + + // Object Properties. + ui->page_properties->setLayout(properiesForm_); + properiesForm_->addRow(objectDetails_.name.label, objectDetails_.name.value); + properiesForm_->addRow(objectDetails_.objectType.label, + objectDetails_.objectType.value); + properiesForm_->addRow(reinterpret_cast(&transformPanel_)); + properiesForm_->addRow(reinterpret_cast(&scalePanel_)); + ui->toolBox->setCurrentWidget(ui->page_properties); + + // Shader views. + ui->page_shaders->setLayout(shaderForm_); + shaderForm_->addRow(vertex_.path.label, vertex_.path.value); + shaderForm_->addRow(vertex_.editor); + shaderForm_->addRow(fragment_.path.label, fragment_.path.value); + shaderForm_->addRow(fragment_.editor); } void ToolBox::updateFocus(const QString & name) { auto object = - Qtk::QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name); + QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name); if (object != Q_NULLPTR) { - removePages(); - createPageProperties(object); - createPageShader(object); + refreshProperties(object); + refreshShaders(object); + } +} + +ToolBox::SpinBox3D::SpinBox3D(QLayout * layout, const char * l) : + label(new QLabel(tr(l))), x(new QDoubleSpinBox), y(new QDoubleSpinBox), + z(new QDoubleSpinBox), fields({x, y, z}) +{ + // The layout owns the widget and will clean it up on destruction. + layout->addWidget(label); + for (const auto & f : fields) { + layout->addWidget(f); + f->setMinimum(std::numeric_limits::lowest()); + f->setSingleStep(0.1); + f->setFixedWidth(75); } } @@ -39,121 +72,52 @@ ToolBox::~ToolBox() delete ui; } -void ToolBox::removePages() +void ToolBox::refreshProperties(const Object * object) { - // Remove all existing pages. - for (size_t i = 0; i < ui->toolBox->count(); i++) { - delete ui->toolBox->widget(i); - ui->toolBox->removeItem(i); - } -} - -void ToolBox::createTransformPanel(const Object * object) -{ - auto rowLayout = transformPanel_.layout = new QHBoxLayout; - transformPanel_.spinBox.label = new QLabel(tr("Translation:")); - rowLayout->addWidget(transformPanel_.spinBox.label); - int minWidth = 75; - for (size_t i = 0; i < 3; i++) { - QDoubleSpinBox * spinBox; - if (i == 0) { - spinBox = transformPanel_.spinBox.x = new QDoubleSpinBox; - connect(spinBox, - &QDoubleSpinBox::valueChanged, - object, - &Object::setTranslationX); - } else if (i == 1) { - spinBox = transformPanel_.spinBox.y = new QDoubleSpinBox; - connect(spinBox, - &QDoubleSpinBox::valueChanged, - object, - &Object::setTranslationY); - } else if (i == 2) { - spinBox = transformPanel_.spinBox.z = new QDoubleSpinBox; - connect(spinBox, - &QDoubleSpinBox::valueChanged, - object, - &Object::setTranslationZ); - } - spinBox->setMinimum(std::numeric_limits::lowest()); - spinBox->setSingleStep(0.1); - spinBox->setValue(object->getTransform().getTranslation()[i]); - spinBox->setFixedWidth(minWidth); - - rowLayout->addWidget(spinBox); - } - - // Add the layout for this panel to the layout for the primary widget. - formLayout_->addRow(transformPanel_.layout); -} - -void ToolBox::createPageProperties(const Object * object) -{ - auto transform = object->getTransform(); - auto * widget = new QWidget; - formLayout_ = new QFormLayout; - widget->setLayout(formLayout_); - - ui->toolBox->addItem(widget, "Properties"); - ui->toolBox->setCurrentWidget(widget); objectDetails_.setDetails(object); - // TODO: Do this in ToolBox ctor after initializing the form. - formLayout_->addRow(objectDetails_.name.label, objectDetails_.name.value); - formLayout_->addRow(objectDetails_.objectType.label, - objectDetails_.objectType.value); - createTransformPanel(object); - - int minWidth = 75; - auto rowLayout = new QHBoxLayout; - rowLayout->addWidget(new QLabel(tr("Scale:"))); + // Reconnect transform panel controls to the new object. + connect(transformPanel_.spinBox.x, + &QDoubleSpinBox::valueChanged, + object, + &Object::setTranslationX); + connect(transformPanel_.spinBox.y, + &QDoubleSpinBox::valueChanged, + object, + &Object::setTranslationY); + connect(transformPanel_.spinBox.z, + &QDoubleSpinBox::valueChanged, + object, + &Object::setTranslationZ); + // Set the values in the spin box to the object's current X,Y,Z position. + auto transform = object->getTransform(); for (size_t i = 0; i < 3; i++) { - auto spinBox = new QDoubleSpinBox; - spinBox->setMinimum(std::numeric_limits::lowest()); - spinBox->setSingleStep(0.1); - spinBox->setValue(transform.getScale()[i]); - spinBox->setFixedWidth(minWidth); - rowLayout->addWidget(spinBox); - - if (i == 0) { - connect( - spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleX); - } else if (i == 1) { - connect( - spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleY); - } else if (i == 2) { - connect( - spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleZ); - } + transformPanel_.spinBox.fields[i]->setValue(transform.getTranslation()[i]); + } + + // Reconnect scale panel controls to the new object. + connect(scalePanel_.spinBox.x, + &QDoubleSpinBox::valueChanged, + object, + &Object::setScaleX); + connect(scalePanel_.spinBox.y, + &QDoubleSpinBox::valueChanged, + object, + &Object::setScaleY); + connect(scalePanel_.spinBox.z, + &QDoubleSpinBox::valueChanged, + object, + &Object::setScaleZ); + // Set the values in the spin box to the object's current X,Y,Z scale. + for (size_t i = 0; i < 3; i++) { + scalePanel_.spinBox.fields[i]->setValue(transform.getScale()[i]); } - formLayout_->addRow(rowLayout); } -void ToolBox::createPageShader(const Object * object) +void ToolBox::refreshShaders(const Object * object) { - // Shaders page. - auto widget = new QWidget; - ui->toolBox->addItem(widget, "Shaders"); - auto mainLayout = new QFormLayout; - auto rowLayout = new QHBoxLayout; - rowLayout->addWidget(new QLabel("Vertex Shader:")); - rowLayout->addWidget(new QLabel(object->getVertexShader().c_str())); - mainLayout->addRow(rowLayout); - - auto shaderView = new QTextEdit; - shaderView->setReadOnly(true); - shaderView->setText(object->getVertexShaderSourceCode().c_str()); - mainLayout->addRow(shaderView); - - rowLayout = new QHBoxLayout; - rowLayout->addWidget(new QLabel("Fragment Shader:")); - rowLayout->addWidget(new QLabel(object->getFragmentShader().c_str())); - mainLayout->addRow(rowLayout); - - shaderView = new QTextEdit; - shaderView->setReadOnly(true); - shaderView->setText(object->getFragmentShaderSourceCode().c_str()); - mainLayout->addRow(shaderView); - - widget->setLayout(mainLayout); + vertex_.path.setItem(object->getVertexShader().c_str()); + vertex_.editor->setText(object->getVertexShaderSourceCode().c_str()); + fragment_.path.setItem(object->getFragmentShader().c_str()); + fragment_.editor->setText(object->getFragmentShaderSourceCode().c_str()); } diff --git a/src/designer-plugins/toolbox.h b/src/designer-plugins/toolbox.h index 075862f..18a3905 100644 --- a/src/designer-plugins/toolbox.h +++ b/src/designer-plugins/toolbox.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "qtk/scene.h" @@ -27,7 +28,7 @@ namespace Ui namespace Qtk { - class ToolBox : public QDockWidget + class ToolBox final : public QDockWidget { Q_OBJECT @@ -40,18 +41,9 @@ namespace Qtk ~ToolBox(); - void removePages(); + void refreshProperties(const Object * object); - /** - * Creates the transform panel and controls. - * - * @param object The Qtk::Object associated with this panel. - */ - void createTransformPanel(const Object * object); - - void createPageProperties(const Object * object); - - void createPageShader(const Object * object); + void refreshShaders(const Object * object); void updateFocus(const QString & name); @@ -65,11 +57,17 @@ namespace Qtk struct ObjectDetails { /// Single item containing a label and value. struct Item { - explicit Item(QWidget * parent) : - label(new QLabel(parent)), value(new QLabel(parent)) + explicit Item(QWidget * parent, + const char * l = "Item:", + const char * v = "") : + label(new QLabel(tr(l), parent)), + value(new QLabel(tr(v), parent)) { + value->setText(v); } + void setItem(const QString & v) { setItem(label->text(), v); } + void setItem(const QString & l, const QString & v) { label->setText(l); @@ -82,7 +80,7 @@ namespace Qtk /// We pass the parent widget so that Qt handles releasing memory. explicit ObjectDetails(QWidget * parent) : - name(parent), objectType(parent) + name(parent, "Name:"), objectType(parent, "ObjectType:") { } @@ -100,28 +98,49 @@ namespace Qtk /// Spinbox with 3 fields and label. struct SpinBox3D { + /// We pass a layout to ensure Qt will clean up resources. + explicit SpinBox3D(QLayout * layout, const char * l = "SpinBox3D:"); + QLabel * label; QDoubleSpinBox * x; QDoubleSpinBox * y; QDoubleSpinBox * z; + std::array fields; }; /// Transform controls and layout. - struct TransformPanel { + class SpinBoxHorizontal3D : QWidget + { + public: + explicit SpinBoxHorizontal3D( + QWidget * parent, const char * l = "SpinBoxHorizontal3D:") : + QWidget(parent), layout(new QHBoxLayout(this)), spinBox(layout, l) + { + } QHBoxLayout * layout; SpinBox3D spinBox; }; - TransformPanel transformPanel_; + SpinBoxHorizontal3D transformPanel_, scalePanel_; - /// Scale controls and layout. - struct ScalePanel { - QHBoxLayout * layout; - SpinBox3D spinBox; + class ShaderView + { + public: + explicit ShaderView(QWidget * parent = nullptr, + const char * l = "ShaderView:") : + path(parent, l), editor(new QTextEdit(parent)) + { + editor->setReadOnly(true); + } + + /// Shader name and path on disk. + ObjectDetails::Item path; + /// Read-only (for now) display of the shader source code. + QTextEdit * editor; }; - ScalePanel scalePanel_; + ShaderView vertex_, fragment_; - /// The root layout for the primary widget. - QFormLayout * formLayout_; + QFormLayout * properiesForm_; + QFormLayout * shaderForm_; Ui::ToolBox * ui; };