Mon, 20 Jun 2022 21:14:17 +0300
Fix pick scene rendering: we cannot use glReadPixels when using multisampling, so we need to render the pick scene to a separate frame buffer
#include <QColorDialog> #include <QTableView> #include <QStyleFactory> #include "colorselectdialog.h" #include "ui_colorselectdialog.h" #include "uiutilities.h" ColorSelectDialog::ColorSelectDialog(const ColorTable& colorTable, QWidget *parent) : QDialog{parent}, ui{*new Ui_ColorSelectDialog}, colorTable{colorTable} { this->ui.setupUi(this); this->makeColorButtons(); connect(this->ui.filter, &QLineEdit::textEdited, this, &ColorSelectDialog::populateColors); this->updateSelectedColorTexts(); connect(this->ui.colorIndex, qOverload<int>(&QSpinBox::valueChanged), this, &ColorSelectDialog::spinboxEdited); connect(this->ui.directColorButton, &QPushButton::clicked, this, &ColorSelectDialog::chooseDirectColor); connect(this->ui.buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(this->ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); this->populateColors(); } ColorSelectDialog::~ColorSelectDialog() { delete &this->ui; } ldraw::Color colorFromButton(QAbstractButton* button) { return {button->property("_colorIndex").value<qint32>()}; } void ColorSelectDialog::makeColorButtons() { this->buttons.reserve(this->colorTable.size()); for ( auto iterator = std::begin(this->colorTable); iterator != std::end(this->colorTable); ++iterator ) { const qint32 index = iterator->first.index; const ColorDefinition& colordef = iterator->second; QPushButton* const button = new QPushButton{QString::number(index), this}; button->setMinimumSize({40, 40}); button->setToolTip(colordef.displayName); const QColor face = colorFace({index}, colorTable).value_or(QColor{}); uiutilities::colorizeWidget(button, face); button->setProperty("_colorIndex", index); button->setCheckable(true); connect(button, &QAbstractButton::clicked, this, &ColorSelectDialog::handleButtonClick); this->buttons.push_back(button); } std::sort( std::begin(this->buttons), std::end(this->buttons), [](QAbstractButton* button_1, QAbstractButton* button_2) { return colorFromButton(button_1) < colorFromButton(button_2); } ); } void ColorSelectDialog::populateColors() { delete this->ui.colorFrame->layout(); if (this->buttons.size() > 0) { QGridLayout* gridLayout = new QGridLayout{}; this->ui.colorFrame->setLayout(gridLayout); const int columnsPerRow = 8; int i = 0; for ( auto iterator = std::begin(this->buttons); iterator != std::end(this->buttons); ++iterator ) { QPushButton* const button = *iterator; const bool filtered = this->filterColor(colorFromButton(button)); button->setVisible(filtered); if (filtered) { const int row = i / columnsPerRow; const int column = i % columnsPerRow; gridLayout->addWidget(button, row, column); i += 1; } } } } void ColorSelectDialog::updateSelectedColorTexts() { const QString displayName = colorDisplayName(this->selectedColor, this->colorTable).value_or(QStringLiteral("???")); this->ui.selectedColorName->setText(displayName); const QColor face = colorFace(this->selectedColor, colorTable).value_or(QColor{}); uiutilities::colorizeWidget(this->ui.selectedColorName, face); this->ui.colorIndex->setValue(this->selectedColor.index); for (QPushButton* button : this->buttons) { ldraw::Color buttonColor = colorFromButton(button); button->setChecked(buttonColor == this->selectedColor); } } void ColorSelectDialog::handleButtonClick() { QAbstractButton* button = qobject_cast<QAbstractButton*>(this->sender()); if (button != nullptr) { this->setCurrentColor(colorFromButton(button)); } } void ColorSelectDialog::spinboxEdited() { this->setCurrentColor(ldraw::Color{this->ui.colorIndex->value()}); } void ColorSelectDialog::chooseDirectColor() { QColorDialog dialog; const std::optional<QColor> face = colorFace(this->selectedColor, this->colorTable); if (face.has_value()) { dialog.setCurrentColor(*face); } if (dialog.exec()) { this->setCurrentColor(directColor(dialog.selectedColor())); } } bool ColorSelectDialog::filterColor(ldraw::Color color) const { const QString& filterText = this->ui.filter->text(); if (filterText.isEmpty()) { return true; } else { const std::optional<QString> name = colorDisplayName(color, colorTable); return name.value_or(QString{}).contains(filterText, Qt::CaseInsensitive); } } void ColorSelectDialog::setCurrentColor(ColorIndex color) { this->selectedColor = color; this->updateSelectedColorTexts(); } ldraw::Color ColorSelectDialog::currentColor() const { return this->selectedColor; }