/*############################################################################## ## Author: Shaun Reed ## ## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ## ## About: Toolbox plugin for object details and options ## ## ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ################################################################################ */ #include "toolbox.h" #include "qtkwidget.h" #include "ui_toolbox.h" #include #include using namespace Qtk; ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), objectDetails_(this), transformPanel_(this), scalePanel_(this), vertex_(this, "Vertex Shader:"), fragment_(this, "Fragment Shader:"), properiesForm_(new QFormLayout), shaderForm_(new QFormLayout), ui(new Ui::ToolBox), objectFocus_(Q_NULLPTR) { 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(reinterpret_cast(&vertex_)); shaderForm_->addRow(reinterpret_cast(&fragment_)); } void ToolBox::updateFocus(const QString & name) { auto object = QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name); // If we can't find the object show a warning. if (object == Q_NULLPTR) { qDebug() << "Failed to find selected object: " << name << "; Clearing object panels."; } // We should still pass the nullptr here if we failed to find the object // above. objectFocus_ = object; refreshProperties(object); refreshShaders(object); } void ToolBox::clearFocus() { objectFocus_ = Q_NULLPTR; refreshProperties(objectFocus_); refreshShaders(objectFocus_); } ToolBox::SpinBox3D::SpinBox3D(QWidget * parent, const char * l) : QWidget(parent), layout(new QHBoxLayout(this)), label(new QLabel(tr(l))) { // The layout owns the widget and will clean it up on destruction. layout->addWidget(label); for (const auto & f : fields) { layout->addWidget(f->spinBox); f->spinBox->setMinimum(std::numeric_limits::lowest()); f->spinBox->setSingleStep(0.1); f->spinBox->setFixedWidth(75); } } void ToolBox::SpinBox::disconnect() const { Object::disconnect(connection); } void ToolBox::TransformPanel::setObject(const Qtk::Object * object) { // Zero the panel contents if there is no object selected. if (object == Q_NULLPTR) { spinBox3D.clear(); return; } // Reconnect translation panel controls to the new object. const std::vector binds = {&Object::setTranslationX, &Object::setTranslationY, &Object::setTranslationZ}; for (size_t i = 0; i < spinBox3D.fields.size(); i++) { auto * f = spinBox3D.fields[i]; // Disconnect before changing spin box value. f->disconnect(); // Set the values in the spin box to the object's current X,Y,Z f->spinBox->setValue(object->getTransform().getTranslation()[i]); // Reconnect to bind spin box value to the new object's position. f->connection = connect(f->spinBox, &QDoubleSpinBox::valueChanged, object, binds[i]); } } void ToolBox::ScalePanel::setObject(const Qtk::Object * object) { // Zero the panel contents if there is no object selected. if (object == Q_NULLPTR) { spinBox3D.clear(); return; } // Reconnect scale panel controls to the new object. const std::vector binds = { &Object::setScaleX, &Object::setScaleY, &Object::setScaleZ}; for (size_t i = 0; i < spinBox3D.fields.size(); i++) { auto * f = spinBox3D.fields[i]; // Disconnect before changing spin box value. f->disconnect(); // Set the values in the spin box to the object's current X,Y,Z f->spinBox->setValue(object->getTransform().getScale()[i]); // Reconnect to bind spin box value to the new object's scale. f->connection = connect(f->spinBox, &QDoubleSpinBox::valueChanged, object, binds[i]); } } ToolBox::~ToolBox() { delete ui; } void ToolBox::refreshProperties(const Object * object) { // Refresh to show the new object's details. objectDetails_.setObject(object); // Reconnect transform panel controls to the new object. transformPanel_.setObject(object); scalePanel_.setObject(object); } void ToolBox::refreshShaders(const Object * object) { // Zero the panel contents if there is no object selected. if (object == Q_NULLPTR) { vertex_.clear(); fragment_.clear(); return; } vertex_.path.setValue(object->getVertexShader().c_str()); vertex_.editor->setText(object->getVertexShaderSourceCode().c_str()); fragment_.path.setValue(object->getFragmentShader().c_str()); fragment_.editor->setText(object->getFragmentShaderSourceCode().c_str()); } void ToolBox::refresh(const Object * object) { refreshProperties(object); refreshShaders(object); }