From 7e14e3f9687cdcac4fe5ebe7b61f1ca1eb6d0f48 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Sun, 13 Apr 2025 18:32:06 +0200 Subject: [PATCH] feat(editor): spinbox for floats --- core/src/objects/base/member.h | 1 + core/src/objects/part.cpp | 1 + editor/panes/propertiesview.cpp | 93 ++++++++++++++++++++++++++++----- editor/panes/propertiesview.h | 5 ++ 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/core/src/objects/base/member.h b/core/src/objects/base/member.h index 6800478..5306eab 100644 --- a/core/src/objects/base/member.h +++ b/core/src/objects/base/member.h @@ -47,6 +47,7 @@ std::function memberFunctionOf(void(T::*func)(std::strin enum PropertyFlags { PROP_HIDDEN = 1 << 0, // Hidden from the editor PROP_NOSAVE = 1 << 1, // Do not serialize + PROP_UNIT_FLOAT = 1 << 2, // Float between 0 and 1 }; enum PropertyCategory { diff --git a/core/src/objects/part.cpp b/core/src/objects/part.cpp index bee17db..73921f2 100644 --- a/core/src/objects/part.cpp +++ b/core/src/objects/part.cpp @@ -109,6 +109,7 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par .backingField = &transparency, .type = &Data::Float::TYPE, .codec = fieldCodecOf(), + .flags = PROP_UNIT_FLOAT, .category = PROP_CATEGORY_APPEARENCE, }} } diff --git a/editor/panes/propertiesview.cpp b/editor/panes/propertiesview.cpp index 93fc735..41b3ac3 100644 --- a/editor/panes/propertiesview.cpp +++ b/editor/panes/propertiesview.cpp @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -14,10 +16,12 @@ #include #include #include +#include class CustomItemDelegate : public QStyledItemDelegate { + PropertiesView* view; public: - CustomItemDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} + CustomItemDelegate(PropertiesView* parent) : view(parent), QStyledItemDelegate(parent) {} void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override { // https://stackoverflow.com/a/76645757/16255372 @@ -32,10 +36,72 @@ public: } else { option->state &= ~QStyle::State_Selected; - QWidget* parentWidget = dynamic_cast(parent()); - option->backgroundBrush = parentWidget->palette().dark(); + option->backgroundBrush = view->palette().dark(); } }; + + QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { + if (index.column() == 0) return nullptr; + + if (!index.parent().isValid() || !view->currentInstance || view->currentInstance->expired()) return nullptr; + InstanceRef inst = view->currentInstance->lock(); + + std::string propertyName = view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString(); + PropertyMeta meta = inst->GetPropertyMeta(propertyName).value(); + Data::Variant currentValue = inst->GetPropertyValue(propertyName).value(); + + if (meta.type == &Data::Float::TYPE) { + QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); + spinBox->setValue(currentValue.get()); + + if (meta.flags & PROP_UNIT_FLOAT) { + spinBox->setMinimum(0); + spinBox->setMaximum(1); + } + + return spinBox; + } else if (meta.type == &Data::Int::TYPE) { + QSpinBox* spinBox = new QSpinBox(parent); + spinBox->setValue(currentValue.get()); + + return spinBox; + } else if (meta.type == &Data::String::TYPE) { + QLineEdit* lineEdit = new QLineEdit(parent); + lineEdit->setText(QString::fromStdString(currentValue.get())); + + return lineEdit; + } + + return nullptr; + } + + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const override { + editor->setGeometry(option.rect.adjusted(-view->indentation(), 0, -view->indentation(), 0)); + } + + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { + if (index.column() == 0) return; + + if (!index.parent().isValid() || !view->currentInstance || view->currentInstance->expired()) return; + InstanceRef inst = view->currentInstance->lock(); + + std::string propertyName = view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString(); + PropertyMeta meta = inst->GetPropertyMeta(propertyName).value(); + + if (meta.type == &Data::Float::TYPE) { + QDoubleSpinBox* spinBox = dynamic_cast(editor); + + inst->SetPropertyValue(propertyName, Data::Float((float)spinBox->value())); + } else if (meta.type == &Data::Int::TYPE) { + QSpinBox* spinBox = dynamic_cast(editor); + + inst->SetPropertyValue(propertyName, Data::Int((float)spinBox->value())); + } else if (meta.type == &Data::String::TYPE) { + QLineEdit* lineEdit = dynamic_cast(editor); + + inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString())); + } + } }; PropertiesView::PropertiesView(QWidget* parent): @@ -68,7 +134,6 @@ QStringList PROPERTY_CATEGORY_NAMES { "Surface" }; - QModelIndex PropertiesView::indexAt(const QPoint &point) const { return QTreeWidget::indexAt(point + QPoint(indentation(), 0)); } @@ -163,16 +228,16 @@ void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) { if (!item->parent() || !currentInstance || currentInstance->expired()) return; InstanceRef inst = currentInstance->lock(); - std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString(); - PropertyMeta meta = inst->GetPropertyMeta(propertyName).value(); + // std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString(); + // PropertyMeta meta = inst->GetPropertyMeta(propertyName).value(); - if (meta.type == &Data::String::TYPE) { - inst->SetPropertyValue(propertyName, Data::String(item->data(1, Qt::EditRole).toString().toStdString())); - } else if (meta.type == &Data::Bool::TYPE) { - inst->SetPropertyValue(propertyName, Data::Bool(item->checkState(1))); - } else { - inst->SetPropertyValue(propertyName, meta.type->fromString(item->data(1, Qt::EditRole).toString().toStdString())); - } + // if (meta.type == &Data::String::TYPE) { + // inst->SetPropertyValue(propertyName, Data::String(item->data(1, Qt::EditRole).toString().toStdString())); + // } else if (meta.type == &Data::Bool::TYPE) { + // inst->SetPropertyValue(propertyName, Data::Bool(item->checkState(1))); + // } else { + // inst->SetPropertyValue(propertyName, meta.type->fromString(item->data(1, Qt::EditRole).toString().toStdString())); + // } - update(indexFromItem(item, column)); + // update(indexFromItem(item, column)); } \ No newline at end of file diff --git a/editor/panes/propertiesview.h b/editor/panes/propertiesview.h index a283b26..86e0c7b 100644 --- a/editor/panes/propertiesview.h +++ b/editor/panes/propertiesview.h @@ -5,11 +5,16 @@ class Ui_MainWindow; +class CustomItemDelegate; + class PropertiesView : public QTreeWidget { Q_DECLARE_PRIVATE(QTreeView) std::optional currentInstance; void propertyChanged(QTreeWidgetItem *item, int column); + void activateProperty(QTreeWidgetItem *item, int column); + + friend CustomItemDelegate; protected: void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override; QModelIndex indexAt(const QPoint &point) const override;