2025-01-12 16:18:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
2025-01-28 19:14:12 +00:00
|
|
|
#include <vector>
|
2025-01-12 16:18:03 +00:00
|
|
|
#include <memory>
|
2025-01-23 10:29:50 +00:00
|
|
|
#include <optional>
|
2025-01-12 16:18:03 +00:00
|
|
|
#include <string>
|
2025-01-28 19:14:12 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <optional>
|
|
|
|
#include <string>
|
|
|
|
#include <variant>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
#include <../include/expected.hpp>
|
|
|
|
|
2025-01-28 20:27:33 +00:00
|
|
|
#include "member.h"
|
2025-01-28 19:14:12 +00:00
|
|
|
|
|
|
|
class Instance;
|
|
|
|
typedef std::shared_ptr<Instance>(*InstanceConstructor)();
|
2025-01-12 16:18:03 +00:00
|
|
|
|
|
|
|
// Struct describing information about an instance
|
|
|
|
struct InstanceType {
|
|
|
|
InstanceType* super; // May be null
|
|
|
|
std::string className;
|
|
|
|
InstanceConstructor constructor;
|
2025-01-18 17:50:56 +00:00
|
|
|
std::string explorerIcon = "";
|
2025-01-12 16:18:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Base class for all instances in the data model
|
2025-01-17 23:11:00 +00:00
|
|
|
// Note: enable_shared_from_this HAS to be public or else its field will not be populated
|
|
|
|
// Maybe this could be replaced with a friendship? But that seems unnecessary.
|
|
|
|
// https://stackoverflow.com/q/56415222/16255372
|
|
|
|
class Instance : public std::enable_shared_from_this<Instance> {
|
2025-01-12 16:18:03 +00:00
|
|
|
private:
|
|
|
|
std::optional<std::weak_ptr<Instance>> parent;
|
|
|
|
std::vector<std::shared_ptr<Instance>> children;
|
2025-01-28 19:14:12 +00:00
|
|
|
|
|
|
|
std::optional<std::vector<std::string>> cachedMemberList;
|
2025-02-01 13:18:53 +00:00
|
|
|
|
|
|
|
bool ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent);
|
2025-01-12 17:38:23 +00:00
|
|
|
protected:
|
2025-01-29 21:41:24 +00:00
|
|
|
std::unique_ptr<MemberMap> memberMap;
|
2025-01-28 19:14:12 +00:00
|
|
|
|
2025-01-12 17:38:23 +00:00
|
|
|
Instance(InstanceType*);
|
|
|
|
virtual ~Instance();
|
2025-01-23 10:29:50 +00:00
|
|
|
|
|
|
|
virtual void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent);
|
2025-01-12 16:18:03 +00:00
|
|
|
public:
|
|
|
|
static InstanceType* TYPE;
|
|
|
|
std::string name;
|
|
|
|
|
2025-01-12 17:38:23 +00:00
|
|
|
// Instance is abstract, so it should not implement GetClass directly
|
|
|
|
virtual InstanceType* GetClass() = 0;
|
2025-02-01 13:18:53 +00:00
|
|
|
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
|
2025-01-12 16:18:03 +00:00
|
|
|
std::optional<std::shared_ptr<Instance>> GetParent();
|
|
|
|
inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; }
|
2025-01-17 08:24:18 +00:00
|
|
|
|
|
|
|
// Utility functions
|
2025-01-17 23:11:00 +00:00
|
|
|
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
2025-01-28 19:14:12 +00:00
|
|
|
|
|
|
|
// Properties
|
|
|
|
// Do I like using expected?
|
2025-01-29 21:41:24 +00:00
|
|
|
tl::expected<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
|
|
|
tl::expected<void, MemberNotFound> SetPropertyValue(std::string name, Data::Variant value);
|
2025-01-28 19:14:12 +00:00
|
|
|
tl::expected<PropertyMeta, MemberNotFound> GetPropertyMeta(std::string name);
|
|
|
|
// Returning a list of property names feels kinda janky. Is this really the way to go?
|
|
|
|
std::vector<std::string> GetProperties();
|
2025-01-12 16:18:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::shared_ptr<Instance> InstanceRef;
|
|
|
|
typedef std::weak_ptr<Instance> InstanceRefWeak;
|