diff --git a/core/src/datatypes/base.cpp b/core/src/datatypes/base.cpp index fe01029..8faf6b1 100644 --- a/core/src/datatypes/base.cpp +++ b/core/src/datatypes/base.cpp @@ -1,5 +1,7 @@ #include "base.h" #include "meta.h" +#include +#include #define IMPL_WRAPPER_CLASS(CLASS_NAME, WRAPPED_TYPE, TYPE_NAME) Data::CLASS_NAME::CLASS_NAME(WRAPPED_TYPE in) : value(in) {} \ Data::CLASS_NAME::~CLASS_NAME() = default; \ @@ -45,7 +47,7 @@ Data::Variant Data::Bool::Deserialize(pugi::xml_node node) { return Data::Bool(node.text().as_bool()); } -Data::Variant Data::Bool::FromString(std::string string) { +std::optional Data::Bool::FromString(std::string string) { return Data::Bool(string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y'); } @@ -58,21 +60,29 @@ Data::Variant Data::Int::Deserialize(pugi::xml_node node) { return Data::Int(node.text().as_int()); } -Data::Variant Data::Int::FromString(std::string string) { - return Data::Int(std::stoi(string)); +std::optional Data::Int::FromString(std::string string) { + char* endPos; + int value = (int)std::strtol(string.c_str(), &endPos, 10); + if (endPos == string.c_str()) return std::nullopt; + return Data::Int(value); } const Data::String Data::Float::ToString() const { - return Data::String(std::to_string(value)); + std::stringstream stream; + stream << std::noshowpoint << value; + return Data::String(stream.str()); } Data::Variant Data::Float::Deserialize(pugi::xml_node node) { return Data::Float(node.text().as_float()); } -Data::Variant Data::Float::FromString(std::string string) { - return Data::Float(std::stof(string)); +std::optional Data::Float::FromString(std::string string) { + char* endPos; + float value = std::strtof(string.c_str(), &endPos); + if (endPos == string.c_str()) return std::nullopt; + return Data::Float(value); } @@ -84,6 +94,6 @@ Data::Variant Data::String::Deserialize(pugi::xml_node node) { return Data::String(node.text().as_string()); } -Data::Variant Data::String::FromString(std::string string) { +std::optional Data::String::FromString(std::string string) { return Data::String(string); } \ No newline at end of file diff --git a/core/src/datatypes/base.h b/core/src/datatypes/base.h index cd86cde..bef50a9 100644 --- a/core/src/datatypes/base.h +++ b/core/src/datatypes/base.h @@ -2,6 +2,7 @@ #include #include +#include #include #define DEF_WRAPPER_CLASS(CLASS_NAME, WRAPPED_TYPE) class CLASS_NAME : public Data::Base { \ @@ -16,13 +17,13 @@ public: \ virtual const Data::String ToString() const override; \ virtual void Serialize(pugi::xml_node node) const override; \ static Data::Variant Deserialize(pugi::xml_node node); \ - static Data::Variant FromString(std::string); \ + static std::optional FromString(std::string); \ }; namespace Data { class Variant; typedef std::function Deserializer; - typedef std::function FromString; + typedef std::function(std::string)> FromString; struct TypeInfo { std::string name; diff --git a/core/src/datatypes/vector.cpp b/core/src/datatypes/vector.cpp index a96de69..0444df6 100644 --- a/core/src/datatypes/vector.cpp +++ b/core/src/datatypes/vector.cpp @@ -21,7 +21,7 @@ Data::Vector3 Data::Vector3::ONE(1, 1, 1); const Data::String Data::Vector3::ToString() const { // https://stackoverflow.com/a/46424921/16255372 - std::ostringstream stream; + std::stringstream stream; stream << std::setprecision(8) << std::noshowpoint << X() << ", " << Y() << ", " << Z(); return stream.str(); } @@ -80,11 +80,11 @@ Data::Variant Data::Vector3::Deserialize(pugi::xml_node node) { return Data::Vector3(node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float()); } -Data::Variant Data::Vector3::FromString(std::string string) { +std::optional Data::Vector3::FromString(std::string string) { float components[3]; for (int i = 0; i < 3; i++) { - if (string.length() == 0) return Data::Vector3(0, 0, 0); + if (string.length() == 0) return std::nullopt; while (string[0] == ' ' && string.length() > 0) string.erase(0, 1); size_t nextPos = string.find(","); if (nextPos == -1) nextPos = string.length(); @@ -93,7 +93,7 @@ Data::Variant Data::Vector3::FromString(std::string string) { char* cpos; float value = std::strtof(term.c_str(), &cpos); - if (cpos == term.c_str()) return Data::Vector3(0, 0, 0); + if (cpos == term.c_str()) return std::nullopt; components[i] = value; } diff --git a/core/src/datatypes/vector.h b/core/src/datatypes/vector.h index c3587a0..cb1ef9a 100644 --- a/core/src/datatypes/vector.h +++ b/core/src/datatypes/vector.h @@ -27,7 +27,7 @@ namespace Data { virtual void Serialize(pugi::xml_node node) const override; static Data::Variant Deserialize(pugi::xml_node node); - static Data::Variant FromString(std::string); + static std::optional FromString(std::string); operator glm::vec3() const; operator rp::Vector3() const; diff --git a/editor/panes/propertiesview.cpp b/editor/panes/propertiesview.cpp index d75a001..86bc93c 100644 --- a/editor/panes/propertiesview.cpp +++ b/editor/panes/propertiesview.cpp @@ -40,7 +40,7 @@ public: } }; - QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { + 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; @@ -84,6 +84,35 @@ public: editor->setGeometry(option.rect.adjusted(-view->indentation(), 0, -view->indentation(), 0)); } + void setEditorData(QWidget *editor, 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(); + Data::Variant currentValue = inst->GetPropertyValue(propertyName).value(); + + if (meta.type == &Data::Float::TYPE) { + QDoubleSpinBox* spinBox = dynamic_cast(editor); + + spinBox->setValue(currentValue.get()); + } else if (meta.type == &Data::Int::TYPE) { + QSpinBox* spinBox = dynamic_cast(editor); + + spinBox->setValue(currentValue.get()); + } else if (meta.type == &Data::String::TYPE) { + QLineEdit* lineEdit = dynamic_cast(editor); + + lineEdit->setText(QString::fromStdString((std::string)currentValue.get())); + } else if (meta.type->fromString) { + QLineEdit* lineEdit = dynamic_cast(editor); + + lineEdit->setText(QString::fromStdString((std::string)currentValue.ToString())); + } + } + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { if (index.column() == 0) return; @@ -97,18 +126,24 @@ public: QDoubleSpinBox* spinBox = dynamic_cast(editor); inst->SetPropertyValue(propertyName, Data::Float((float)spinBox->value())); + model->setData(index, spinBox->value()); } else if (meta.type == &Data::Int::TYPE) { QSpinBox* spinBox = dynamic_cast(editor); inst->SetPropertyValue(propertyName, Data::Int((float)spinBox->value())); + model->setData(index, spinBox->value()); } else if (meta.type == &Data::String::TYPE) { QLineEdit* lineEdit = dynamic_cast(editor); inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString())); + model->setData(index, lineEdit->text()); } else if (meta.type->fromString) { QLineEdit* lineEdit = dynamic_cast(editor); - inst->SetPropertyValue(propertyName, meta.type->fromString(lineEdit->text().toStdString())); + std::optional parsedResult = meta.type->fromString(lineEdit->text().toStdString()); + if (!parsedResult) return; + inst->SetPropertyValue(propertyName, parsedResult.value()); + model->setData(index, QString::fromStdString(parsedResult.value().ToString())); } } };