Compare commits
No commits in common. "ea71c6f47700a81bf99c48a12c713264db82ead1" and "ff1f9be5c5b28572c1750ed94504a439807cf1ba" have entirely different histories.
ea71c6f477
...
ff1f9be5c5
11 changed files with 2583 additions and 114 deletions
17
core/src/error/error.cpp
Normal file
17
core/src/error/error.cpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "error.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
Error::Error(std::string message) : message(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Error::getMessage() {
|
||||||
|
return this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Error::logMessage(Logger::LogLevel logLevel) {
|
||||||
|
Logger::log(this->message, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Error::logMessageFatal() {
|
||||||
|
Logger::fatalError(this->message);
|
||||||
|
}
|
|
@ -5,15 +5,13 @@
|
||||||
|
|
||||||
// Base class for all errors
|
// Base class for all errors
|
||||||
class Error {
|
class Error {
|
||||||
std::string _errorType;
|
std::string message;
|
||||||
std::string _message;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline Error(std::string errorType, std::string message) : _errorType(errorType), _message(message) {}
|
Error(std::string message);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline std::string errorType() { return this->_errorType; }
|
std::string getMessage();
|
||||||
inline std::string message() { return this->_message; }
|
void logMessage(Logger::LogLevel logLevel = Logger::LogLevel::ERROR);
|
||||||
inline void logMessage(Logger::LogLevel logLevel = Logger::LogLevel::ERROR) { Logger::log(this->_message, logLevel); }
|
void logMessageFatal();
|
||||||
void logMessageFatal() { Logger::fatalError(this->_message); }
|
|
||||||
};
|
};
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
class NoSuchInstance : public Error {
|
|
||||||
public:
|
|
||||||
inline NoSuchInstance(std::string className) : Error("NoSuchInstance", "Cannot create instance of unknown type " + className) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class NoSuchService : public Error {
|
|
||||||
public:
|
|
||||||
inline NoSuchService(std::string className) : Error("NoSuchService", "Cannot insert service of unknown type " + className) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ServiceAlreadyExists : public Error {
|
|
||||||
public:
|
|
||||||
inline ServiceAlreadyExists(std::string className) : Error("ServiceAlreadyExists", "Service " + className + " is already inserted") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MemberNotFound : public Error {
|
|
||||||
public:
|
|
||||||
inline MemberNotFound(std::string className, std::string memberName) : Error("MemberNotFound", "Could not find member '" + memberName + "' in class " + className) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssignToReadOnlyMember : public Error {
|
|
||||||
public:
|
|
||||||
inline AssignToReadOnlyMember(std::string className, std::string memberName) : Error("AssignToReadOnlyMember", "Attempt to assign value to read-only member '" + memberName + "' in class " + className) {}
|
|
||||||
};
|
|
|
@ -1,68 +1,59 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "error/error.h"
|
#include "error.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
struct DUMMY_VALUE {};
|
struct DUMMY_VALUE {};
|
||||||
|
|
||||||
template <typename T_Result, typename ...T_Errors>
|
template <typename Result, typename ...E>
|
||||||
class [[nodiscard]] result {
|
class [[nodiscard]] result {
|
||||||
static_assert(std::conjunction_v<std::is_base_of<Error, T_Errors>...>, "result<T_Errors...> requires T_Errors to derive from Error");
|
struct ErrorContainer {
|
||||||
|
std::variant<E...> error;
|
||||||
struct error_state {
|
|
||||||
std::variant<T_Errors...> error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct success_state {
|
struct SuccessContainer {
|
||||||
T_Result success;
|
Result success;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::variant<success_state, error_state> value;
|
std::variant<SuccessContainer, ErrorContainer> value;
|
||||||
public:
|
public:
|
||||||
result(T_Result success) : value(success_state { success }) {}
|
result(Result success) : value(SuccessContainer { success }) {}
|
||||||
result(std::variant<T_Errors...> error) : value(error_state { error }) {}
|
result(std::variant<E...> error) : value(ErrorContainer { error }) {}
|
||||||
template <typename T_Error, std::enable_if_t<std::disjunction_v<std::is_same<T_Error, T_Errors>...>, int> = 0>
|
|
||||||
result(T_Error error) : value(error_state { error }) {}
|
|
||||||
|
|
||||||
// Expects the result to be successful, otherwise panic with error message
|
// Expects the result to be successful, otherwise panic with error message
|
||||||
T_Result expect(std::string errMsg = "Expected result to contain success") {
|
Result expect(std::string errMsg = "Unwrapped a result with failure value") {
|
||||||
if (isSuccess())
|
if (is_success())
|
||||||
return std::get<success_state>(value).success;
|
return std::get<SuccessContainer>(value).success;
|
||||||
std::visit([&](auto&& it) {
|
Logger::fatalError(errMsg);
|
||||||
Logger::fatalErrorf("Unwrapped a result with error value: [%s] %s\n\t%s", it.errorType(), it.message(), errMsg);
|
|
||||||
}, error().value());
|
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSuccess() { return std::holds_alternative<success_state>(value); }
|
bool is_success() { return std::holds_alternative<SuccessContainer>(value); }
|
||||||
bool isError() { return std::holds_alternative<error_state>(value); }
|
bool is_error() { return std::holds_alternative<ErrorContainer>(value); }
|
||||||
|
|
||||||
std::optional<T_Result> success() { return isSuccess() ? std::get<success_state>(value).success : std::nullopt; }
|
std::optional<Result> success() { return is_success() ? std::get<SuccessContainer>(value).success : std::nullopt; }
|
||||||
std::optional<std::variant<T_Errors...>> error() { return isError() ? std::make_optional(std::get<error_state>(value).error) : std::nullopt; }
|
std::optional<std::variant<E...>> error() { return is_error() ? std::make_optional(std::get<ErrorContainer>(value).error) : std::nullopt; }
|
||||||
|
|
||||||
void logError(Logger::LogLevel logLevel = Logger::LogLevel::ERROR) {
|
void logError(Logger::LogLevel logLevel = Logger::LogLevel::ERROR) {
|
||||||
if (isSuccess()) return;
|
if (is_success()) return;
|
||||||
std::visit([&](auto&& it) {
|
std::visit([&](auto&& it) {
|
||||||
it.logMessage(logLevel);
|
it.logMessage(logLevel);
|
||||||
}, error().value());
|
}, error().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equivalent to .success
|
// Equivalent to .success
|
||||||
operator std::optional<T_Result>() { return success(); }
|
operator std::optional<Result>() { return success(); }
|
||||||
operator bool() { return isSuccess(); }
|
operator bool() { return is_success(); }
|
||||||
bool operator !() { return isError(); }
|
bool operator !() { return is_error(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ...T_Errors>
|
template <typename ...E>
|
||||||
class [[nodiscard]] fallible : public result<DUMMY_VALUE, T_Errors...> {
|
class fallible : public result<DUMMY_VALUE, E...> {
|
||||||
public:
|
public:
|
||||||
fallible() : result<DUMMY_VALUE, T_Errors...>(DUMMY_VALUE {}) {}
|
fallible() : result<DUMMY_VALUE, E...>(DUMMY_VALUE {}) {}
|
||||||
fallible(std::variant<T_Errors...> error) : result<DUMMY_VALUE, T_Errors...>(error) {}
|
fallible(std::variant<E...> error) : result<DUMMY_VALUE, E...>(error) {}
|
||||||
template <typename T_Error, std::enable_if_t<std::disjunction_v<std::is_same<T_Error, T_Errors>...>, int> = 0>
|
|
||||||
fallible(T_Error error) : result<DUMMY_VALUE, T_Errors...>(error) {}
|
|
||||||
};
|
};
|
|
@ -2,7 +2,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "datatypes/meta.h"
|
#include "datatypes/meta.h"
|
||||||
#include "datatypes/base.h"
|
#include "datatypes/base.h"
|
||||||
#include "error/instance.h"
|
|
||||||
#include "objects/base/member.h"
|
#include "objects/base/member.h"
|
||||||
#include "objects/meta.h"
|
#include "objects/meta.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
@ -158,27 +157,24 @@ void Instance::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child,
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
result<Data::Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) {
|
tl::expected<Data::Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) {
|
||||||
auto meta_ = GetPropertyMeta(name);
|
auto meta = GetPropertyMeta(name);
|
||||||
if (!meta_) return MemberNotFound(GetClass()->className, name);
|
if (!meta) return tl::make_unexpected(MemberNotFound());
|
||||||
auto meta = meta_.expect();
|
|
||||||
|
|
||||||
return meta.codec.read(meta.backingField);
|
return meta->codec.read(meta->backingField);
|
||||||
}
|
}
|
||||||
|
|
||||||
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::SetPropertyValue(std::string name, Data::Variant value) {
|
tl::expected<void, MemberNotFound> Instance::SetPropertyValue(std::string name, Data::Variant value) {
|
||||||
auto meta_ = GetPropertyMeta(name);
|
auto meta = GetPropertyMeta(name);
|
||||||
if (!meta_) return MemberNotFound(GetClass()->className, name);
|
if (!meta || meta->flags & PROP_READONLY) return tl::make_unexpected(MemberNotFound());
|
||||||
auto meta = meta_.expect();
|
|
||||||
if (meta.flags & PROP_READONLY) AssignToReadOnlyMember(GetClass()->className, name);
|
|
||||||
|
|
||||||
meta.codec.write(value, meta.backingField);
|
meta->codec.write(value, meta->backingField);
|
||||||
if (meta.updateCallback) meta.updateCallback.value()(name);
|
if (meta->updateCallback) meta->updateCallback.value()(name);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
result<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name) {
|
tl::expected<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name) {
|
||||||
MemberMap* current = &*memberMap;
|
MemberMap* current = &*memberMap;
|
||||||
while (true) {
|
while (true) {
|
||||||
// We look for the property in current member map
|
// We look for the property in current member map
|
||||||
|
@ -190,7 +186,7 @@ result<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name)
|
||||||
|
|
||||||
// It is not found, If there are no other maps to search, return null
|
// It is not found, If there are no other maps to search, return null
|
||||||
if (!current->super.has_value())
|
if (!current->super.has_value())
|
||||||
return MemberNotFound(GetClass()->className, name);
|
return tl::make_unexpected(MemberNotFound());
|
||||||
|
|
||||||
// Search in the parent
|
// Search in the parent
|
||||||
current = current->super->get();
|
current = current->super->get();
|
||||||
|
@ -227,12 +223,12 @@ void Instance::Serialize(pugi::xml_node parent) {
|
||||||
// Add properties
|
// Add properties
|
||||||
pugi::xml_node propertiesNode = node.append_child("Properties");
|
pugi::xml_node propertiesNode = node.append_child("Properties");
|
||||||
for (std::string name : GetProperties()) {
|
for (std::string name : GetProperties()) {
|
||||||
PropertyMeta meta = GetPropertyMeta(name).expect("Meta of declared property is missing");
|
PropertyMeta meta = GetPropertyMeta(name).value();
|
||||||
if (meta.flags & PropertyFlags::PROP_NOSAVE) continue; // This property should not be serialized. Skip...
|
if (meta.flags & PropertyFlags::PROP_NOSAVE) continue; // This property should not be serialized. Skip...
|
||||||
|
|
||||||
pugi::xml_node propertyNode = propertiesNode.append_child(meta.type->name);
|
pugi::xml_node propertyNode = propertiesNode.append_child(meta.type->name);
|
||||||
propertyNode.append_attribute("name").set_value(name);
|
propertyNode.append_attribute("name").set_value(name);
|
||||||
GetPropertyValue(name).expect("Declared property is missing").Serialize(propertyNode);
|
GetPropertyValue(name)->Serialize(propertyNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add children
|
// Add children
|
||||||
|
@ -244,7 +240,7 @@ void Instance::Serialize(pugi::xml_node parent) {
|
||||||
result<InstanceRef, NoSuchInstance> Instance::Deserialize(pugi::xml_node node) {
|
result<InstanceRef, NoSuchInstance> Instance::Deserialize(pugi::xml_node node) {
|
||||||
std::string className = node.attribute("class").value();
|
std::string className = node.attribute("class").value();
|
||||||
if (INSTANCE_MAP.count(className) == 0) {
|
if (INSTANCE_MAP.count(className) == 0) {
|
||||||
return NoSuchInstance(className);
|
return std::variant<NoSuchInstance>(NoSuchInstance(className));
|
||||||
}
|
}
|
||||||
// This will error if an abstract instance is used in the file. Oh well, not my prob rn.
|
// This will error if an abstract instance is used in the file. Oh well, not my prob rn.
|
||||||
// printf("What are you? A %s sandwich\n", className.c_str());
|
// printf("What are you? A %s sandwich\n", className.c_str());
|
||||||
|
@ -258,18 +254,18 @@ result<InstanceRef, NoSuchInstance> Instance::Deserialize(pugi::xml_node node) {
|
||||||
for (pugi::xml_node propertyNode : propertiesNode) {
|
for (pugi::xml_node propertyNode : propertiesNode) {
|
||||||
std::string propertyName = propertyNode.attribute("name").value();
|
std::string propertyName = propertyNode.attribute("name").value();
|
||||||
auto meta_ = object->GetPropertyMeta(propertyName);
|
auto meta_ = object->GetPropertyMeta(propertyName);
|
||||||
if (!meta_) {
|
if (!meta_.has_value()) {
|
||||||
Logger::fatalErrorf("Attempt to set unknown property '%s' of %s", propertyName.c_str(), object->GetClass()->className.c_str());
|
Logger::fatalErrorf("Attempt to set unknown property '%s' of %s", propertyName.c_str(), object->GetClass()->className.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Data::Variant value = Data::Variant::Deserialize(propertyNode);
|
Data::Variant value = Data::Variant::Deserialize(propertyNode);
|
||||||
object->SetPropertyValue(propertyName, value).expect("Declared property was missing");
|
object->SetPropertyValue(propertyName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read children
|
// Read children
|
||||||
for (pugi::xml_node childNode : node.children("Item")) {
|
for (pugi::xml_node childNode : node.children("Item")) {
|
||||||
result<InstanceRef, NoSuchInstance> child = Instance::Deserialize(childNode);
|
result<InstanceRef, NoSuchInstance> child = Instance::Deserialize(childNode);
|
||||||
if (child.isError()) {
|
if (child.is_error()) {
|
||||||
std::get<NoSuchInstance>(child.error().value()).logMessage();
|
std::get<NoSuchInstance>(child.error().value()).logMessage();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <expected.hpp>
|
#include <expected.hpp>
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
#include "error/instance.h"
|
#include "error/error.h"
|
||||||
#include "error/result.h"
|
#include "error/result.h"
|
||||||
#include "member.h"
|
#include "member.h"
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@ struct InstanceType {
|
||||||
InstanceFlags flags;
|
InstanceFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
class NoSuchInstance : public Error {
|
||||||
|
public:
|
||||||
|
inline NoSuchInstance(std::string className) : Error("Cannot create instance of unknown type " + className) {}
|
||||||
|
};
|
||||||
|
|
||||||
class DescendantsIterator;
|
class DescendantsIterator;
|
||||||
|
|
||||||
|
@ -92,9 +97,10 @@ public:
|
||||||
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
result<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
// Do I like using expected?
|
||||||
fallible<MemberNotFound, AssignToReadOnlyMember> SetPropertyValue(std::string name, Data::Variant value);
|
tl::expected<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
||||||
result<PropertyMeta, MemberNotFound> GetPropertyMeta(std::string name);
|
tl::expected<void, MemberNotFound> SetPropertyValue(std::string name, Data::Variant value);
|
||||||
|
tl::expected<PropertyMeta, MemberNotFound> GetPropertyMeta(std::string name);
|
||||||
// Returning a list of property names feels kinda janky. Is this really the way to go?
|
// Returning a list of property names feels kinda janky. Is this really the way to go?
|
||||||
std::vector<std::string> GetProperties();
|
std::vector<std::string> GetProperties();
|
||||||
|
|
||||||
|
|
|
@ -76,3 +76,5 @@ struct MemberMap {
|
||||||
std::optional<std::unique_ptr<MemberMap>> super;
|
std::optional<std::unique_ptr<MemberMap>> super;
|
||||||
std::map<std::string, PropertyMeta> members;
|
std::map<std::string, PropertyMeta> members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MemberNotFound {};
|
|
@ -82,18 +82,18 @@ void DataModel::DeserializeService(pugi::xml_node node) {
|
||||||
for (pugi::xml_node propertyNode : propertiesNode) {
|
for (pugi::xml_node propertyNode : propertiesNode) {
|
||||||
std::string propertyName = propertyNode.attribute("name").value();
|
std::string propertyName = propertyNode.attribute("name").value();
|
||||||
auto meta_ = object->GetPropertyMeta(propertyName);
|
auto meta_ = object->GetPropertyMeta(propertyName);
|
||||||
if (!meta_) {
|
if (!meta_.has_value()) {
|
||||||
Logger::fatalErrorf("Attempt to set unknown property '%s' of %s", propertyName.c_str(), object->GetClass()->className.c_str());
|
Logger::fatalErrorf("Attempt to set unknown property '%s' of %s", propertyName.c_str(), object->GetClass()->className.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Data::Variant value = Data::Variant::Deserialize(propertyNode);
|
Data::Variant value = Data::Variant::Deserialize(propertyNode);
|
||||||
object->SetPropertyValue(propertyName, value).expect();
|
object->SetPropertyValue(propertyName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add children
|
// Add children
|
||||||
for (pugi::xml_node childNode : node.children("Item")) {
|
for (pugi::xml_node childNode : node.children("Item")) {
|
||||||
result<InstanceRef, NoSuchInstance> child = Instance::Deserialize(childNode);
|
result<InstanceRef, NoSuchInstance> child = Instance::Deserialize(childNode);
|
||||||
if (child.isError()) {
|
if (child.is_error()) {
|
||||||
std::get<NoSuchInstance>(child.error().value()).logMessage();
|
std::get<NoSuchInstance>(child.error().value()).logMessage();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
#include "error/result.h"
|
#include "error/result.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
|
@ -13,6 +14,16 @@ class Workspace;
|
||||||
class DataModel;
|
class DataModel;
|
||||||
class Service;
|
class Service;
|
||||||
|
|
||||||
|
class NoSuchService : public Error {
|
||||||
|
public:
|
||||||
|
inline NoSuchService(std::string className) : Error("Cannot insert service of unknown type " + className) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ServiceAlreadyExists : public Error {
|
||||||
|
public:
|
||||||
|
inline ServiceAlreadyExists(std::string className) : Error("Service " + className + " is already inserted") {}
|
||||||
|
};
|
||||||
|
|
||||||
// The root instance to all objects in the hierarchy
|
// The root instance to all objects in the hierarchy
|
||||||
class DataModel : public Instance {
|
class DataModel : public Instance {
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -41,8 +41,8 @@ public:
|
||||||
|
|
||||||
std::string propertyName = !isComposite ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
std::string propertyName = !isComposite ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
||||||
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
||||||
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
|
PropertyMeta meta = inst->GetPropertyMeta(propertyName).value();
|
||||||
Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect();
|
Data::Variant currentValue = inst->GetPropertyValue(propertyName).value();
|
||||||
|
|
||||||
if (isComposite) {
|
if (isComposite) {
|
||||||
if (meta.type == &Data::Vector3::TYPE) {
|
if (meta.type == &Data::Vector3::TYPE) {
|
||||||
|
@ -107,8 +107,8 @@ public:
|
||||||
|
|
||||||
std::string propertyName = !index.parent().parent().isValid() ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
std::string propertyName = !index.parent().parent().isValid() ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
||||||
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
||||||
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
|
PropertyMeta meta = inst->GetPropertyMeta(propertyName).value();
|
||||||
Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect();
|
Data::Variant currentValue = inst->GetPropertyValue(propertyName).value();
|
||||||
|
|
||||||
if (isComposite) {
|
if (isComposite) {
|
||||||
if (meta.type == &Data::Vector3::TYPE) {
|
if (meta.type == &Data::Vector3::TYPE) {
|
||||||
|
@ -159,19 +159,19 @@ public:
|
||||||
|
|
||||||
std::string propertyName = !index.parent().parent().isValid() ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
std::string propertyName = !index.parent().parent().isValid() ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString()
|
||||||
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
: view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString();
|
||||||
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
|
PropertyMeta meta = inst->GetPropertyMeta(propertyName).value();
|
||||||
|
|
||||||
if (isComposite) {
|
if (isComposite) {
|
||||||
if (meta.type == &Data::Vector3::TYPE) {
|
if (meta.type == &Data::Vector3::TYPE) {
|
||||||
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
|
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
|
||||||
float value = spinBox->value();
|
float value = spinBox->value();
|
||||||
|
|
||||||
Data::Vector3 prev = inst->GetPropertyValue(propertyName).expect().get<Data::Vector3>();
|
Data::Vector3 prev = inst->GetPropertyValue(propertyName).value().get<Data::Vector3>();
|
||||||
Data::Vector3 newVector = componentName == "X" ? Data::Vector3(value, prev.Y(), prev.Z())
|
Data::Vector3 newVector = componentName == "X" ? Data::Vector3(value, prev.Y(), prev.Z())
|
||||||
: componentName == "Y" ? Data::Vector3(prev.X(), value, prev.Z())
|
: componentName == "Y" ? Data::Vector3(prev.X(), value, prev.Z())
|
||||||
: componentName == "Z" ? Data::Vector3(prev.X(), prev.Y(), value) : prev;
|
: componentName == "Z" ? Data::Vector3(prev.X(), prev.Y(), value) : prev;
|
||||||
|
|
||||||
inst->SetPropertyValue(propertyName, newVector).expect();
|
inst->SetPropertyValue(propertyName, newVector);
|
||||||
view->rebuildCompositeProperty(view->itemFromIndex(index.parent()), &Data::Vector3::TYPE, newVector);
|
view->rebuildCompositeProperty(view->itemFromIndex(index.parent()), &Data::Vector3::TYPE, newVector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -182,24 +182,24 @@ public:
|
||||||
if (meta.type == &Data::Float::TYPE) {
|
if (meta.type == &Data::Float::TYPE) {
|
||||||
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
|
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
|
||||||
|
|
||||||
inst->SetPropertyValue(propertyName, Data::Float((float)spinBox->value())).expect();
|
inst->SetPropertyValue(propertyName, Data::Float((float)spinBox->value()));
|
||||||
model->setData(index, spinBox->value());
|
model->setData(index, spinBox->value());
|
||||||
} else if (meta.type == &Data::Int::TYPE) {
|
} else if (meta.type == &Data::Int::TYPE) {
|
||||||
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor);
|
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor);
|
||||||
|
|
||||||
inst->SetPropertyValue(propertyName, Data::Int((float)spinBox->value())).expect();
|
inst->SetPropertyValue(propertyName, Data::Int((float)spinBox->value()));
|
||||||
model->setData(index, spinBox->value());
|
model->setData(index, spinBox->value());
|
||||||
} else if (meta.type == &Data::String::TYPE) {
|
} else if (meta.type == &Data::String::TYPE) {
|
||||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
||||||
|
|
||||||
inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString())).expect();
|
inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString()));
|
||||||
model->setData(index, lineEdit->text());
|
model->setData(index, lineEdit->text());
|
||||||
} else if (meta.type == &Data::Color3::TYPE) {
|
} else if (meta.type == &Data::Color3::TYPE) {
|
||||||
QColorDialog* colorDialog = dynamic_cast<QColorDialog*>(editor);
|
QColorDialog* colorDialog = dynamic_cast<QColorDialog*>(editor);
|
||||||
|
|
||||||
QColor color = colorDialog->currentColor();
|
QColor color = colorDialog->currentColor();
|
||||||
Data::Color3 color3(color.redF(), color.greenF(), color.blueF());
|
Data::Color3 color3(color.redF(), color.greenF(), color.blueF());
|
||||||
inst->SetPropertyValue(propertyName, color3).expect();
|
inst->SetPropertyValue(propertyName, color3);
|
||||||
model->setData(index, QString::fromStdString(color3.ToString()), Qt::DisplayRole);
|
model->setData(index, QString::fromStdString(color3.ToString()), Qt::DisplayRole);
|
||||||
model->setData(index, color, Qt::DecorationRole);
|
model->setData(index, color, Qt::DecorationRole);
|
||||||
} else if (meta.type->fromString) {
|
} else if (meta.type->fromString) {
|
||||||
|
@ -207,7 +207,7 @@ public:
|
||||||
|
|
||||||
std::optional<Data::Variant> parsedResult = meta.type->fromString(lineEdit->text().toStdString());
|
std::optional<Data::Variant> parsedResult = meta.type->fromString(lineEdit->text().toStdString());
|
||||||
if (!parsedResult) return;
|
if (!parsedResult) return;
|
||||||
inst->SetPropertyValue(propertyName, parsedResult.value()).expect();
|
inst->SetPropertyValue(propertyName, parsedResult.value());
|
||||||
model->setData(index, QString::fromStdString(parsedResult.value().ToString()));
|
model->setData(index, QString::fromStdString(parsedResult.value().ToString()));
|
||||||
view->rebuildCompositeProperty(view->itemFromIndex(index), meta.type, parsedResult.value());
|
view->rebuildCompositeProperty(view->itemFromIndex(index), meta.type, parsedResult.value());
|
||||||
}
|
}
|
||||||
|
@ -283,8 +283,8 @@ void PropertiesView::setSelected(std::optional<InstanceRef> instance) {
|
||||||
std::vector<std::string> properties = inst->GetProperties();
|
std::vector<std::string> properties = inst->GetProperties();
|
||||||
|
|
||||||
for (std::string property : properties) {
|
for (std::string property : properties) {
|
||||||
PropertyMeta meta = inst->GetPropertyMeta(property).expect();
|
PropertyMeta meta = inst->GetPropertyMeta(property).value();
|
||||||
Data::Variant currentValue = inst->GetPropertyValue(property).expect();
|
Data::Variant currentValue = inst->GetPropertyValue(property).value();
|
||||||
|
|
||||||
if (meta.type == &Data::CFrame::TYPE) continue;
|
if (meta.type == &Data::CFrame::TYPE) continue;
|
||||||
|
|
||||||
|
@ -330,10 +330,10 @@ void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) {
|
||||||
InstanceRef inst = currentInstance->lock();
|
InstanceRef inst = currentInstance->lock();
|
||||||
|
|
||||||
std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString();
|
std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString();
|
||||||
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
|
PropertyMeta meta = inst->GetPropertyMeta(propertyName).value();
|
||||||
|
|
||||||
if (meta.type == &Data::Bool::TYPE) {
|
if (meta.type == &Data::Bool::TYPE) {
|
||||||
inst->SetPropertyValue(propertyName, Data::Bool(item->checkState(1))).expect();
|
inst->SetPropertyValue(propertyName, Data::Bool(item->checkState(1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2476
include/expected.hpp
Normal file
2476
include/expected.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue