refactor(misc): replaced instances of optional<shared_ptr> with nullable shared_ptr

This commit is contained in:
maelstrom 2025-08-19 19:31:48 +02:00
parent bb81aff4fd
commit 7352b53a94
29 changed files with 139 additions and 146 deletions

View file

@ -8,9 +8,8 @@
#include <memory> #include <memory>
class Instance; class Instance;
// typedef std::function<void(std::shared_ptr<Instance> element, std::optional<std::shared_ptr<Instance>> newParent)> HierarchyUpdateHandler; typedef std::function<void(std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent)> HierarchyPreUpdateHandler;
typedef std::function<void(std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent)> HierarchyPreUpdateHandler; typedef std::function<void(std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent)> HierarchyPostUpdateHandler;
typedef std::function<void(std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent)> HierarchyPostUpdateHandler;
typedef std::function<void(std::shared_ptr<Instance> instance, std::string property, Variant newValue)> PropertyUpdateHandler; typedef std::function<void(std::shared_ptr<Instance> instance, std::string property, Variant newValue)> PropertyUpdateHandler;
// TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS // TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS

View file

@ -151,9 +151,9 @@ static int inst_index(lua_State* L) {
} }
// Look for child // Look for child
std::optional<std::shared_ptr<Instance>> child = inst->FindFirstChild(key); nullable std::shared_ptr<Instance> child = inst->FindFirstChild(key);
if (child) { if (child) {
InstanceRef(child.value()).PushLuaValue(L); InstanceRef(child).PushLuaValue(L);
return 1; return 1;
} }
@ -173,7 +173,7 @@ static int inst_newindex(lua_State* L) {
if (meta->flags & PROP_READONLY) if (meta->flags & PROP_READONLY)
return luaL_error(L, "'%s' of %s is read-only", key.c_str(), inst->GetClass()->className.c_str()); return luaL_error(L, "'%s' of %s is read-only", key.c_str(), inst->GetClass()->className.c_str());
if (key == "Parent" && inst->IsParentLocked()) if (key == "Parent" && inst->IsParentLocked())
return luaL_error(L, "Cannot set property Parent (%s) of %s, parent is locked", inst->GetParent() ? inst->GetParent().value()->name.c_str() : "NULL", inst->GetClass()->className.c_str()); return luaL_error(L, "Cannot set property Parent (%s) of %s, parent is locked", inst->GetParent() ? inst->GetParent()->name.c_str() : "NULL", inst->GetClass()->className.c_str());
// TODO: Make this work for enums, this is not a solution!! // TODO: Make this work for enums, this is not a solution!!
result<Variant, LuaCastError> value = meta->type.descriptor->fromLuaValue(L, -1); result<Variant, LuaCastError> value = meta->type.descriptor->fromLuaValue(L, -1);

View file

@ -44,21 +44,16 @@ Instance::Instance(const InstanceType* type) {
Instance::~Instance () { Instance::~Instance () {
} }
template <typename T>
std::weak_ptr<T> optional_to_weak(std::optional<std::shared_ptr<T>> a) {
return a ? a.value() : std::weak_ptr<T>();
}
// TODO: Test this // TODO: Test this
bool Instance::ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent) { bool Instance::ancestryContinuityCheck(nullable std::shared_ptr<Instance> newParent) {
for (std::optional<std::shared_ptr<Instance>> currentParent = newParent; currentParent.has_value(); currentParent = currentParent.value()->GetParent()) { for (std::shared_ptr<Instance> currentParent = newParent; currentParent != nullptr; currentParent = currentParent->GetParent()) {
if (currentParent.value() == this->shared_from_this()) if (currentParent == this->shared_from_this())
return false; return false;
} }
return true; return true;
} }
bool Instance::SetParent(std::optional<std::shared_ptr<Instance>> newParent) { bool Instance::SetParent(nullable std::shared_ptr<Instance> newParent) {
if (this->parentLocked || !ancestryContinuityCheck(newParent)) if (this->parentLocked || !ancestryContinuityCheck(newParent))
return false; return false;
@ -70,10 +65,10 @@ bool Instance::SetParent(std::optional<std::shared_ptr<Instance>> newParent) {
oldParent->children.erase(std::find(oldParent->children.begin(), oldParent->children.end(), this->shared_from_this())); oldParent->children.erase(std::find(oldParent->children.begin(), oldParent->children.end(), this->shared_from_this()));
} }
// Add ourselves to the new parent // Add ourselves to the new parent
if (newParent.has_value()) { if (newParent != nullptr) {
newParent.value()->children.push_back(this->shared_from_this()); newParent->children.push_back(this->shared_from_this());
} }
this->parent = optional_to_weak(newParent); this->parent = newParent;
// TODO: Add code for sending signals for parent updates // TODO: Add code for sending signals for parent updates
// TODO: Yeahhh maybe this isn't the best way of doing this? // TODO: Yeahhh maybe this isn't the best way of doing this?
if (hierarchyPostUpdateHandler.has_value()) hierarchyPostUpdateHandler.value()(this->shared_from_this(), lastParent, newParent); if (hierarchyPostUpdateHandler.has_value()) hierarchyPostUpdateHandler.value()(this->shared_from_this(), lastParent, newParent);
@ -85,21 +80,21 @@ bool Instance::SetParent(std::optional<std::shared_ptr<Instance>> newParent) {
return true; return true;
} }
void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedChild, std::optional<std::shared_ptr<Instance>> newParent) { void Instance::updateAncestry(nullable std::shared_ptr<Instance> updatedChild, nullable std::shared_ptr<Instance> newParent) {
auto oldDataModel = _dataModel; auto oldDataModel = _dataModel;
auto oldWorkspace = _workspace; auto oldWorkspace = _workspace;
// Update parent data model and workspace, if applicable // Update parent data model and workspace, if applicable
if (GetParent()) { if (GetParent() != nullptr) {
this->_dataModel = GetParent().value()->GetClass() == &DataModel::TYPE ? std::dynamic_pointer_cast<DataModel>(GetParent().value()) : GetParent().value()->_dataModel; this->_dataModel = GetParent()->GetClass() == &DataModel::TYPE ? std::dynamic_pointer_cast<DataModel>(GetParent()) : GetParent()->_dataModel;
this->_workspace = GetParent().value()->GetClass() == &Workspace::TYPE ? std::dynamic_pointer_cast<Workspace>(GetParent().value()) : GetParent().value()->_workspace; this->_workspace = GetParent()->GetClass() == &Workspace::TYPE ? std::dynamic_pointer_cast<Workspace>(GetParent()) : GetParent()->_workspace;
} else { } else {
this->_dataModel = {}; this->_dataModel = {};
this->_workspace = {}; this->_workspace = {};
} }
OnAncestryChanged(updatedChild, newParent); OnAncestryChanged(updatedChild, newParent);
AncestryChanged->Fire({updatedChild.has_value() ? InstanceRef(updatedChild.value()) : InstanceRef(), newParent.has_value() ? InstanceRef(newParent.value()) : InstanceRef()}); AncestryChanged->Fire({updatedChild != nullptr ? InstanceRef(updatedChild) : InstanceRef(), newParent != nullptr ? InstanceRef(newParent) : InstanceRef()});
// Old workspace used to exist, and workspaces differ // Old workspace used to exist, and workspaces differ
if (!oldWorkspace.expired() && oldWorkspace != _workspace) { if (!oldWorkspace.expired() && oldWorkspace != _workspace) {
@ -108,7 +103,7 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
// New workspace exists, and workspaces differ // New workspace exists, and workspaces differ
if (!_workspace.expired() && (_workspace != oldWorkspace)) { if (!_workspace.expired() && (_workspace != oldWorkspace)) {
OnWorkspaceAdded(!oldWorkspace.expired() ? std::make_optional(oldWorkspace.lock()) : std::nullopt, _workspace.lock()); OnWorkspaceAdded(oldWorkspace.expired() ? nullptr : oldWorkspace.lock(), _workspace.lock());
} }
// Update ancestry in descendants // Update ancestry in descendants
@ -117,23 +112,22 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
} }
} }
std::optional<std::shared_ptr<DataModel>> Instance::dataModel() { nullable std::shared_ptr<DataModel> Instance::dataModel() {
return (_dataModel.expired()) ? std::nullopt : std::make_optional(_dataModel.lock()); return _dataModel.expired() ? nullptr : _dataModel.lock();
} }
std::optional<std::shared_ptr<Workspace>> Instance::workspace() { nullable std::shared_ptr<Workspace> Instance::workspace() {
return (_workspace.expired()) ? std::nullopt : std::make_optional(_workspace.lock()); return _workspace.expired() ? nullptr : _workspace.lock();
} }
std::optional<std::shared_ptr<Instance>> Instance::GetParent() { nullable std::shared_ptr<Instance> Instance::GetParent() {
if (parent.expired()) return std::nullopt; return parent.expired() ? nullptr : parent.lock();
return parent.lock();
} }
void Instance::Destroy() { void Instance::Destroy() {
if (parentLocked) return; if (parentLocked) return;
// TODO: Implement proper distruction stuff // TODO: Implement proper distruction stuff
SetParent(std::nullopt); SetParent(nullptr);
parentLocked = true; parentLocked = true;
} }
@ -143,12 +137,12 @@ bool Instance::IsA(std::string className) {
return cur != nullptr; return cur != nullptr;
} }
std::optional<std::shared_ptr<Instance>> Instance::FindFirstChild(std::string name) { nullable std::shared_ptr<Instance> Instance::FindFirstChild(std::string name) {
for (auto child : children) { for (auto child : children) {
if (child->name == name) if (child->name == name)
return child; return child;
} }
return std::nullopt; return nullptr;
} }
static std::shared_ptr<Instance> DUMMY_INSTANCE; static std::shared_ptr<Instance> DUMMY_INSTANCE;
@ -164,15 +158,15 @@ bool Instance::IsParentLocked() {
return this->parentLocked; return this->parentLocked;
} }
void Instance::OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) { void Instance::OnParentUpdated(nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
// Empty stub // Empty stub
} }
void Instance::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) { void Instance::OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent) {
// Empty stub // Empty stub
} }
void Instance::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) { void Instance::OnWorkspaceAdded(nullable std::shared_ptr<Workspace> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
// Empty stub // Empty stub
} }
@ -230,7 +224,7 @@ fallible<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyVa
this->name = (std::string)value.get<std::string>(); this->name = (std::string)value.get<std::string>();
} else if (name == "Parent") { } else if (name == "Parent") {
std::weak_ptr<Instance> ref = value.get<InstanceRef>(); std::weak_ptr<Instance> ref = value.get<InstanceRef>();
SetParent(ref.expired() ? std::nullopt : std::make_optional(ref.lock())); SetParent(ref.expired() ? nullptr : ref.lock());
} else if (name == "ClassName") { } else if (name == "ClassName") {
return AssignToReadOnlyMember(GetClass()->className, name); return AssignToReadOnlyMember(GetClass()->className, name);
} else { } else {
@ -430,9 +424,9 @@ DescendantsIterator::self_type DescendantsIterator::operator++(int _) {
} }
// If we've hit the end of this item's children, move one up // If we've hit the end of this item's children, move one up
while (current->GetParent() && current->GetParent().value()->GetChildren().size() <= size_t(siblingIndex.back() + 1)) { while (current->GetParent() != nullptr && current->GetParent()->GetChildren().size() <= size_t(siblingIndex.back() + 1)) {
siblingIndex.pop_back(); siblingIndex.pop_back();
current = current->GetParent().value(); current = current->GetParent();
// But not if one up is null or the root element // But not if one up is null or the root element
if (!current->GetParent() || current == root) { if (!current->GetParent() || current == root) {
@ -443,12 +437,12 @@ DescendantsIterator::self_type DescendantsIterator::operator++(int _) {
// Now move to the next sibling // Now move to the next sibling
siblingIndex.back()++; siblingIndex.back()++;
current = current->GetParent().value()->GetChildren()[siblingIndex.back()]; current = current->GetParent()->GetChildren()[siblingIndex.back()];
return *this; return *this;
} }
std::optional<std::shared_ptr<Instance>> Instance::Clone(RefStateClone state) { nullable std::shared_ptr<Instance> Instance::Clone(RefStateClone state) {
if (state == nullptr) state = std::make_shared<__RefStateClone>(); if (state == nullptr) state = std::make_shared<__RefStateClone>();
std::shared_ptr<Instance> newInstance = GetClass()->constructor(); std::shared_ptr<Instance> newInstance = GetClass()->constructor();
@ -494,9 +488,9 @@ std::optional<std::shared_ptr<Instance>> Instance::Clone(RefStateClone state) {
// Clone children // Clone children
for (std::shared_ptr<Instance> child : GetChildren()) { for (std::shared_ptr<Instance> child : GetChildren()) {
std::optional<std::shared_ptr<Instance>> clonedChild = child->Clone(state); nullable std::shared_ptr<Instance> clonedChild = child->Clone(state);
if (clonedChild) if (clonedChild)
newInstance->AddChild(clonedChild.value()); newInstance->AddChild(clonedChild);
} }
return newInstance; return newInstance;
@ -521,12 +515,12 @@ std::vector<std::pair<std::string, std::shared_ptr<Instance>>> Instance::GetRefe
std::string Instance::GetFullName() { std::string Instance::GetFullName() {
std::string currentName = name; std::string currentName = name;
std::optional<std::shared_ptr<Instance>> currentParent = GetParent(); nullable std::shared_ptr<Instance> currentParent = GetParent();
while (currentParent.has_value() && !currentParent.value()->IsA("DataModel")) { while (currentParent && !currentParent->IsA("DataModel")) {
currentName = currentParent.value()->name + "." + currentName; currentName = currentParent->name + "." + currentName;
currentParent = currentParent.value()->GetParent(); currentParent = currentParent->GetParent();
} }
return currentName; return currentName;

View file

@ -16,6 +16,7 @@
#include "error/result.h" #include "error/result.h"
#include "member.h" #include "member.h"
#include "objects/base/refstate.h" #include "objects/base/refstate.h"
#include "utils.h"
class Instance; class Instance;
typedef std::shared_ptr<Instance>(*InstanceConstructor)(); typedef std::shared_ptr<Instance>(*InstanceConstructor)();
@ -59,8 +60,8 @@ private:
std::weak_ptr<DataModel> _dataModel; std::weak_ptr<DataModel> _dataModel;
std::weak_ptr<Workspace> _workspace; std::weak_ptr<Workspace> _workspace;
bool ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent); bool ancestryContinuityCheck(nullable std::shared_ptr<Instance> newParent);
void updateAncestry(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent); void updateAncestry(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent);
friend JointInstance; // This isn't ideal, but oh well friend JointInstance; // This isn't ideal, but oh well
protected: protected:
@ -75,17 +76,17 @@ protected:
virtual void InternalUpdateProperty(std::string name); virtual void InternalUpdateProperty(std::string name);
virtual std::vector<std::string> InternalGetProperties(); virtual std::vector<std::string> InternalGetProperties();
virtual void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent); virtual void OnParentUpdated(nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent);
virtual void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent); virtual void OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent);
virtual void OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace); virtual void OnWorkspaceAdded(nullable std::shared_ptr<Workspace> oldWorkspace, std::shared_ptr<Workspace> newWorkspace);
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace); virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace);
// The root data model this object is a descendant of // The root data model this object is a descendant of
std::optional<std::shared_ptr<DataModel>> dataModel(); nullable std::shared_ptr<DataModel> dataModel();
// The root workspace this object is a descendant of // The root workspace this object is a descendant of
// NOTE: This value is not necessarily present if dataModel is present // NOTE: This value is not necessarily present if dataModel is present
// Objects under services other than workspace will NOT have this field set // Objects under services other than workspace will NOT have this field set
std::optional<std::shared_ptr<Workspace>> workspace(); nullable std::shared_ptr<Workspace> workspace();
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;
std::string name; std::string name;
@ -96,8 +97,8 @@ public:
// Instance is abstract, so it should not implement GetClass directly // Instance is abstract, so it should not implement GetClass directly
virtual const InstanceType* GetClass() = 0; virtual const InstanceType* GetClass() = 0;
static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent); bool SetParent(nullable std::shared_ptr<Instance> newParent);
std::optional<std::shared_ptr<Instance>> GetParent(); nullable std::shared_ptr<Instance> GetParent();
bool IsParentLocked(); bool IsParentLocked();
inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; } inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; }
void Destroy(); void Destroy();
@ -111,7 +112,7 @@ public:
DescendantsIterator GetDescendantsEnd(); DescendantsIterator GetDescendantsEnd();
// Utility functions // Utility functions
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()); }
std::optional<std::shared_ptr<Instance>> FindFirstChild(std::string); nullable std::shared_ptr<Instance> FindFirstChild(std::string);
std::string GetFullName(); std::string GetFullName();
// Properties // Properties
@ -136,7 +137,7 @@ public:
// Serialization // Serialization
void Serialize(pugi::xml_node parent, RefStateSerialize state = {}); void Serialize(pugi::xml_node parent, RefStateSerialize state = {});
static result<std::shared_ptr<Instance>, NoSuchInstance> Deserialize(pugi::xml_node node, RefStateDeserialize state = {}); static result<std::shared_ptr<Instance>, NoSuchInstance> Deserialize(pugi::xml_node node, RefStateDeserialize state = {});
std::optional<std::shared_ptr<Instance>> Clone(RefStateClone state = {}); nullable std::shared_ptr<Instance> Clone(RefStateClone state = {});
}; };
// https://gist.github.com/jeetsukumaran/307264 // https://gist.github.com/jeetsukumaran/307264
@ -158,7 +159,7 @@ public:
self_type operator++(int _); self_type operator++(int _);
private: private:
std::optional<std::shared_ptr<Instance>> root; nullable std::shared_ptr<Instance> root;
std::shared_ptr<Instance> current; std::shared_ptr<Instance> current;
std::vector<int> siblingIndex; std::vector<int> siblingIndex;
}; };

View file

@ -7,9 +7,9 @@
Service::Service(const InstanceType* type) : Instance(type) {} Service::Service(const InstanceType* type) : Instance(type) {}
// Fail if parented to non-datamodel, otherwise lock parent // Fail if parented to non-datamodel, otherwise lock parent
void Service::OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) { void Service::OnParentUpdated(nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
if (!newParent || newParent.value()->GetClass() != &DataModel::TYPE) { if (!newParent || newParent->GetClass() != &DataModel::TYPE) {
Logger::fatalErrorf("Service %s was parented to object of type %s", GetClass()->className.c_str(), newParent ? newParent.value()->GetClass()->className.c_str() : "NULL"); Logger::fatalErrorf("Service %s was parented to object of type %s", GetClass()->className.c_str(), newParent ? newParent->GetClass()->className.c_str() : "NULL");
panic(); panic();
} }

View file

@ -13,7 +13,7 @@ protected:
virtual void InitService(); virtual void InitService();
virtual void OnRun(); virtual void OnRun();
void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) override; void OnParentUpdated(nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) override;
friend class DataModel; friend class DataModel;
}; };

View file

@ -107,14 +107,14 @@ result<std::shared_ptr<Service>, NoSuchService> DataModel::GetService(std::strin
return std::dynamic_pointer_cast<Service>(services[className]); return std::dynamic_pointer_cast<Service>(services[className]);
} }
result<std::optional<std::shared_ptr<Service>>, NoSuchService> DataModel::FindService(std::string className) { result<nullable std::shared_ptr<Service>, NoSuchService> DataModel::FindService(std::string className) {
if (!INSTANCE_MAP[className] || (INSTANCE_MAP[className]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) { if (!INSTANCE_MAP[className] || (INSTANCE_MAP[className]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
return NoSuchService(className); return NoSuchService(className);
} }
if (services.count(className) != 0) if (services.count(className) != 0)
return std::make_optional(std::dynamic_pointer_cast<Service>(services[className])); return std::dynamic_pointer_cast<Service>(services[className]);
return (std::optional<std::shared_ptr<Service>>)std::nullopt; return nullptr;
} }
std::shared_ptr<DataModel> DataModel::CloneModel() { std::shared_ptr<DataModel> DataModel::CloneModel() {
@ -166,11 +166,11 @@ std::shared_ptr<DataModel> DataModel::CloneModel() {
if (!result) if (!result)
continue; continue;
newModel->AddChild(result.value()); newModel->AddChild(result);
// Special case: Ignore instances parented to DataModel which are not services // Special case: Ignore instances parented to DataModel which are not services
if (child->GetClass()->flags & INSTANCE_SERVICE) { if (child->GetClass()->flags & INSTANCE_SERVICE) {
newModel->services[child->GetClass()->className] = std::dynamic_pointer_cast<Service>(result.value()); newModel->services[child->GetClass()->className] = std::dynamic_pointer_cast<Service>(result);
} }
} }

View file

@ -29,7 +29,7 @@ public:
static inline std::shared_ptr<DataModel> New() { return std::make_shared<DataModel>(); }; static inline std::shared_ptr<DataModel> New() { return std::make_shared<DataModel>(); };
result<std::shared_ptr<Service>, NoSuchService> GetService(std::string className); result<std::shared_ptr<Service>, NoSuchService> GetService(std::string className);
result<std::optional<std::shared_ptr<Service>>, NoSuchService> FindService(std::string className); result<nullable std::shared_ptr<Service>, NoSuchService> FindService(std::string className);
template <typename T> template <typename T>
std::shared_ptr<T> GetService() { std::shared_ptr<T> GetService() {
@ -38,10 +38,10 @@ public:
} }
template <typename T> template <typename T>
std::optional<std::shared_ptr<T>> FindService() { nullable std::shared_ptr<T> FindService() {
auto result = FindService(T::TYPE.className).expect("FindService<T>() was called with a non-service instance type"); auto result = FindService(T::TYPE.className).expect("FindService<T>() was called with a non-service instance type");
if (!result) return std::nullopt; if (!result) return nullptr;
return std::dynamic_pointer_cast<T>(result.value()); return std::dynamic_pointer_cast<T>(result);
} }
// Saving/loading // Saving/loading

View file

@ -17,7 +17,7 @@ JointInstance::JointInstance(const InstanceType* type): Instance(type) {
JointInstance::~JointInstance() { JointInstance::~JointInstance() {
} }
void JointInstance::OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) { void JointInstance::OnAncestryChanged(nullable std::shared_ptr<Instance>, nullable std::shared_ptr<Instance>) {
// Destroy and rebuild the joint, it's the simplest solution that actually works // Destroy and rebuild the joint, it's the simplest solution that actually works
breakJoint(); breakJoint();
@ -54,6 +54,6 @@ void JointInstance::onUpdated(std::string property) {
oldPart1 = part1; oldPart1 = part1;
} }
std::optional<std::shared_ptr<Workspace>> JointInstance::workspaceOfPart(std::shared_ptr<BasePart> part) { nullable std::shared_ptr<Workspace> JointInstance::workspaceOfPart(std::shared_ptr<BasePart> part) {
return part->workspace(); return part->workspace();
} }

View file

@ -23,9 +23,9 @@ protected:
// The workspace the joint was created in, if it exists // The workspace the joint was created in, if it exists
std::weak_ptr<Workspace> jointWorkspace; std::weak_ptr<Workspace> jointWorkspace;
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) override; void OnAncestryChanged(nullable std::shared_ptr<Instance>, nullable std::shared_ptr<Instance>) override;
std::optional<std::shared_ptr<Workspace>> workspaceOfPart(std::shared_ptr<BasePart>); nullable std::shared_ptr<Workspace> workspaceOfPart(std::shared_ptr<BasePart>);
void onUpdated(std::string property); void onUpdated(std::string property);
virtual void buildJoint() = 0; virtual void buildJoint() = 0;
virtual void breakJoint() = 0; virtual void breakJoint() = 0;

View file

@ -17,9 +17,9 @@ void Rotate::buildJoint() {
if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return; if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return;
// Don't build the joint if we're not part of either a workspace or JointsService // Don't build the joint if we're not part of either a workspace or JointsService
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return; if ((!GetParent() || GetParent()->GetClass() != &JointsService::TYPE) && workspace() != nullptr) return;
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value(); std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock());
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
// used to be rather than specifying an anchor rotation, so whatever. // used to be rather than specifying an anchor rotation, so whatever.

View file

@ -19,9 +19,9 @@ void RotateV::buildJoint() {
if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return; if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return;
// Don't build the joint if we're not part of either a workspace or JointsService // Don't build the joint if we're not part of either a workspace or JointsService
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return; if ((!GetParent() || GetParent()->GetClass() != &JointsService::TYPE) && workspace() != nullptr) return;
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value(); std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock());
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it

View file

@ -21,9 +21,9 @@ void Snap::buildJoint() {
if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return; if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return;
// Don't build the joint if we're not part of either a workspace or JointsService // Don't build the joint if we're not part of either a workspace or JointsService
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return; if ((!GetParent() || GetParent()->GetClass() != &JointsService::TYPE) && !workspace()) return;
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value(); std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock());
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
// used to be rather than specifying an anchor rotation, so whatever. // used to be rather than specifying an anchor rotation, so whatever.

View file

@ -21,9 +21,9 @@ void Weld::buildJoint() {
if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return; if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !workspaceOfPart(part0.lock()) || workspaceOfPart(part0.lock()) != workspaceOfPart(part1.lock())) return;
// Don't build the joint if we're not part of either a workspace or JointsService // Don't build the joint if we're not part of either a workspace or JointsService
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return; if ((!GetParent() || GetParent()->GetClass() != &JointsService::TYPE) && workspace() != nullptr) return;
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value(); std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock());
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
// used to be rather than specifying an anchor rotation, so whatever. // used to be rather than specifying an anchor rotation, so whatever.

View file

@ -14,7 +14,6 @@
#include "objects/joint/snap.h" #include "objects/joint/snap.h"
#include "rendering/renderer.h" #include "rendering/renderer.h"
#include "enum/surface.h" #include "enum/surface.h"
#include <cstdio>
#include <glm/common.hpp> #include <glm/common.hpp>
#include <memory> #include <memory>
#include <optional> #include <optional>
@ -28,18 +27,18 @@ BasePart::BasePart(const InstanceType* type, PartConstructParams params): PVInst
BasePart::~BasePart() { BasePart::~BasePart() {
// This relies on physicsCommon still existing. Be very careful. // This relies on physicsCommon still existing. Be very careful.
if (this->rigidBody && workspace()) { if (this->rigidBody && workspace() != nullptr) {
workspace().value()->RemoveBody(shared<BasePart>()); workspace()->RemoveBody(shared<BasePart>());
} }
} }
void BasePart::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) { void BasePart::OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent) {
if (this->rigidBody) if (this->rigidBody)
this->rigidBody->setIsActive(workspace().has_value()); this->rigidBody->setIsActive(workspace() != nullptr);
if (workspace()) if (workspace() != nullptr)
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this())); workspace()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
// Destroy joints // Destroy joints
if (!workspace()) BreakJoints(); if (!workspace()) BreakJoints();
@ -47,7 +46,7 @@ void BasePart::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child,
// TODO: Sleeping bodies that touch this one also need to be updated // TODO: Sleeping bodies that touch this one also need to be updated
} }
void BasePart::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) { void BasePart::OnWorkspaceAdded(nullable std::shared_ptr<Workspace> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
newWorkspace->AddBody(shared<BasePart>()); newWorkspace->AddBody(shared<BasePart>());
} }
@ -58,8 +57,8 @@ void BasePart::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
void BasePart::onUpdated(std::string property) { void BasePart::onUpdated(std::string property) {
bool reset = property == "Position" || property == "Rotation" || property == "CFrame" || property == "Size" || property == "Shape"; bool reset = property == "Position" || property == "Rotation" || property == "CFrame" || property == "Size" || property == "Shape";
if (workspace()) if (workspace() != nullptr)
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this())); workspace()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
// When position/rotation/size is manually edited, break all joints, they don't apply anymore // When position/rotation/size is manually edited, break all joints, they don't apply anymore
if (reset) if (reset)
@ -204,7 +203,7 @@ bool BasePart::checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3
return horizOverlap && vertOverlap; return horizOverlap && vertOverlap;
} }
std::optional<std::shared_ptr<JointInstance>> makeJointFromSurfaces(SurfaceType a, SurfaceType b) { nullable std::shared_ptr<JointInstance> makeJointFromSurfaces(SurfaceType a, SurfaceType b) {
if (a == SurfaceType::Weld || b == SurfaceType::Weld || a == SurfaceType::Glue || b == SurfaceType::Glue) return Weld::New(); if (a == SurfaceType::Weld || b == SurfaceType::Weld || a == SurfaceType::Glue || b == SurfaceType::Glue) return Weld::New();
if ((a == SurfaceType::Studs && (b == SurfaceType::Inlet || b == SurfaceType::Universal)) if ((a == SurfaceType::Studs && (b == SurfaceType::Inlet || b == SurfaceType::Universal))
|| (a == SurfaceType::Inlet && (b == SurfaceType::Studs || b == SurfaceType::Universal)) || (a == SurfaceType::Inlet && (b == SurfaceType::Studs || b == SurfaceType::Universal))
@ -214,7 +213,7 @@ std::optional<std::shared_ptr<JointInstance>> makeJointFromSurfaces(SurfaceType
return Rotate::New(); return Rotate::New();
if (a == SurfaceType::Motor) if (a == SurfaceType::Motor)
return RotateV::New(); return RotateV::New();
return std::nullopt; return nullptr;
} }
void BasePart::MakeJoints() { void BasePart::MakeJoints() {
@ -229,7 +228,7 @@ void BasePart::MakeJoints() {
// TEMPORARY // TEMPORARY
// TODO: Use more efficient algorithm to *actually* find nearby parts) // TODO: Use more efficient algorithm to *actually* find nearby parts)
for (auto it = workspace().value()->GetDescendantsStart(); it != workspace().value()->GetDescendantsEnd(); it++) { for (auto it = workspace()->GetDescendantsStart(); it != workspace()->GetDescendantsEnd(); it++) {
std::shared_ptr<Instance> obj = *it; std::shared_ptr<Instance> obj = *it;
if (obj == shared_from_this()) continue; // Skip ourselves if (obj == shared_from_this()) continue; // Skip ourselves
if (!obj->IsA<BasePart>()) continue; if (!obj->IsA<BasePart>()) continue;
@ -276,12 +275,12 @@ void BasePart::MakeJoints() {
auto joint_ = makeJointFromSurfaces(mySurface, otherSurface); auto joint_ = makeJointFromSurfaces(mySurface, otherSurface);
if (!joint_) continue; if (!joint_) continue;
std::shared_ptr<JointInstance> joint = joint_.value(); std::shared_ptr<JointInstance> joint = joint_;
joint->part0 = shared<BasePart>(); joint->part0 = shared<BasePart>();
joint->part1 = otherPart->shared<BasePart>(); joint->part1 = otherPart->shared<BasePart>();
joint->c0 = contact0; joint->c0 = contact0;
joint->c1 = contact1; joint->c1 = contact1;
dataModel().value()->GetService<JointsService>()->AddChild(joint); dataModel()->GetService<JointsService>()->AddChild(joint);
joint->UpdateProperty("Part0"); joint->UpdateProperty("Part0");
Logger::debugf("Made joint between %s and %s!\n", name.c_str(), otherPart->name.c_str()); Logger::debugf("Made joint between %s and %s!\n", name.c_str(), otherPart->name.c_str());

View file

@ -54,9 +54,9 @@ protected:
friend JointInstance; friend JointInstance;
friend PhysWorld; friend PhysWorld;
virtual void OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) override; virtual void OnWorkspaceAdded(nullable std::shared_ptr<Workspace> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) override;
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) override; virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) override;
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) override; void OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent) override;
void onUpdated(std::string); void onUpdated(std::string);
virtual void updateCollider(rp::PhysicsCommon* common) = 0; virtual void updateCollider(rp::PhysicsCommon* common) = 0;

View file

@ -23,7 +23,7 @@ Script::~Script() {
} }
void Script::Run() { void Script::Run() {
std::shared_ptr<ScriptContext> scriptContext = dataModel().value()->GetService<ScriptContext>(); std::shared_ptr<ScriptContext> scriptContext = dataModel()->GetService<ScriptContext>();
lua_State* L = scriptContext->state; lua_State* L = scriptContext->state;
int top = lua_gettop(L); int top = lua_gettop(L);

View file

@ -18,8 +18,8 @@ void JointsService::InitService() {
} }
} }
std::optional<std::shared_ptr<Workspace>> JointsService::jointWorkspace() { nullable std::shared_ptr<Workspace> JointsService::jointWorkspace() {
if (!dataModel()) return std::nullopt; if (!dataModel()) return nullptr;
return dataModel().value()->FindService<Workspace>(); return dataModel()->FindService<Workspace>();
} }

View file

@ -6,7 +6,7 @@
class DEF_INST_SERVICE_(hidden) JointsService : public Service { class DEF_INST_SERVICE_(hidden) JointsService : public Service {
AUTOGEN_PREAMBLE AUTOGEN_PREAMBLE
private: private:
std::optional<std::shared_ptr<Workspace>> jointWorkspace(); nullable std::shared_ptr<Workspace> jointWorkspace();
protected: protected:
void InitService() override; void InitService() override;
bool initialized = false; bool initialized = false;

View file

@ -59,10 +59,10 @@ void ScriptContext::InitService() {
// Add other globals // Add other globals
lua_getglobal(state, "_G"); lua_getglobal(state, "_G");
InstanceRef(dataModel().value()).PushLuaValue(state); InstanceRef(dataModel()).PushLuaValue(state);
lua_setfield(state, -2, "game"); lua_setfield(state, -2, "game");
InstanceRef(dataModel().value()->GetService<Workspace>()).PushLuaValue(state); InstanceRef(dataModel()->GetService<Workspace>()).PushLuaValue(state);
lua_setfield(state, -2, "workspace"); lua_setfield(state, -2, "workspace");
lua_pushlightuserdata(state, this); lua_pushlightuserdata(state, this);

View file

@ -14,7 +14,7 @@ void ServerScriptService::InitService() {
} }
void ServerScriptService::OnRun() { void ServerScriptService::OnRun() {
auto workspace = dataModel().value()->GetService<Workspace>(); auto workspace = dataModel()->GetService<Workspace>();
for (auto it = workspace->GetDescendantsStart(); it != workspace->GetDescendantsEnd(); it++) { for (auto it = workspace->GetDescendantsStart(); it != workspace->GetDescendantsEnd(); it++) {
if (!it->IsA<Script>()) continue; if (!it->IsA<Script>()) continue;
it->CastTo<Script>().expect()->Run(); it->CastTo<Script>().expect()->Run();

View file

@ -42,7 +42,7 @@ void Workspace::OnRun() {
joint->UpdateProperty("Part0"); joint->UpdateProperty("Part0");
} }
for (auto obj : dataModel().value()->GetService<JointsService>()->GetChildren()) { for (auto obj : dataModel()->GetService<JointsService>()->GetChildren()) {
if (!obj->IsA<JointInstance>()) continue; if (!obj->IsA<JointInstance>()) continue;
std::shared_ptr<JointInstance> joint = obj->CastTo<JointInstance>().expect(); std::shared_ptr<JointInstance> joint = obj->CastTo<JointInstance>().expect();
joint->UpdateProperty("Part0"); joint->UpdateProperty("Part0");
@ -63,8 +63,8 @@ void Workspace::PhysicsStep(float deltaTime) {
part->Destroy(); part->Destroy();
// If the parent of the part is a Model, destroy it too // If the parent of the part is a Model, destroy it too
if (parent.has_value() && parent.value()->IsA("Model")) if (parent != nullptr && parent->IsA("Model"))
parent.value()->Destroy(); parent->Destroy();
} }
} }
} }

View file

@ -412,9 +412,9 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
// Traverse to the root model // Traverse to the root model
if (~evt->modifiers() & Qt::AltModifier) { if (~evt->modifiers() & Qt::AltModifier) {
std::optional<std::shared_ptr<Instance>> nextParent = selObject->GetParent(); nullable std::shared_ptr<Instance> nextParent = selObject->GetParent();
while (nextParent.value() && nextParent.value()->IsA("Model")) { while (nextParent && nextParent->IsA("Model")) {
selObject = std::dynamic_pointer_cast<PVInstance>(nextParent.value()); nextParent = selObject->GetParent(); selObject = std::dynamic_pointer_cast<PVInstance>(nextParent); nextParent = selObject->GetParent();
} }
} }

View file

@ -403,8 +403,8 @@ void MainWindow::connectActionHandlers() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>(); std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) { for (std::weak_ptr<Instance> inst : selection->Get()) {
if (inst.expired()) continue; if (inst.expired()) continue;
historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent().value() }); historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent() });
inst.lock()->SetParent(std::nullopt); inst.lock()->SetParent(nullptr);
} }
selection->Set({}); selection->Set({});
historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}}); historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}});
@ -433,9 +433,9 @@ void MainWindow::connectActionHandlers() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>(); std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) { for (std::weak_ptr<Instance> inst : selection->Get()) {
if (inst.expired()) continue; if (inst.expired()) continue;
historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent().value() }); historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent() });
inst.lock()->Serialize(rootDoc); inst.lock()->Serialize(rootDoc);
inst.lock()->SetParent(std::nullopt); inst.lock()->SetParent(nullptr);
} }
selection->Set({}); selection->Set({});
historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}}); historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}});
@ -502,8 +502,8 @@ void MainWindow::connectActionHandlers() {
bool done = false; bool done = false;
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>(); std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (auto object : selection->Get()) { for (auto object : selection->Get()) {
if (firstParent == nullptr && object->GetParent().has_value()) firstParent = object->GetParent().value(); if (!firstParent && object->GetParent() != nullptr) firstParent = object->GetParent();
historyState.push_back(UndoStateInstanceReparented { object, object->GetParent().value(), model }); historyState.push_back(UndoStateInstanceReparented { object, object->GetParent(), model });
object->SetParent(model); object->SetParent(model);
done = true; done = true;
} }
@ -535,13 +535,13 @@ void MainWindow::connectActionHandlers() {
done = true; done = true;
for (auto object : model->GetChildren()) { for (auto object : model->GetChildren()) {
historyState.push_back(UndoStateInstanceReparented { object, object->GetParent().value(), model->GetParent().value() }); historyState.push_back(UndoStateInstanceReparented { object, object->GetParent(), model->GetParent() });
object->SetParent(model->GetParent()); object->SetParent(model->GetParent());
newSelection.push_back(object); newSelection.push_back(object);
} }
historyState.push_back(UndoStateInstanceRemoved { model, model->GetParent().value() }); historyState.push_back(UndoStateInstanceRemoved { model, model->GetParent() });
model->SetParent(std::nullopt); model->SetParent(nullptr);
} }
if (!done) if (!done)

View file

@ -22,24 +22,24 @@ ExplorerModel::ExplorerModel(std::shared_ptr<Instance> dataRoot, QWidget *parent
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
, rootItem(dataRoot) { , rootItem(dataRoot) {
// TODO: Don't use lambdas and handlers like that // TODO: Don't use lambdas and handlers like that
hierarchyPreUpdateHandler = [&](std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) { hierarchyPreUpdateHandler = [&](std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
if (oldParent.has_value()) { if (oldParent) {
auto children = oldParent.value()->GetChildren(); auto children = oldParent->GetChildren();
size_t idx = std::find(children.begin(), children.end(), object) - children.begin(); size_t idx = std::find(children.begin(), children.end(), object) - children.begin();
beginRemoveRows(toIndex(oldParent.value()), idx, idx); beginRemoveRows(toIndex(oldParent), idx, idx);
} }
if (newParent.has_value()) { if (newParent) {
size_t size = newParent.value()->GetChildren().size(); size_t size = newParent->GetChildren().size();
beginInsertRows(toIndex(newParent.value()), size, size); beginInsertRows(toIndex(newParent), size, size);
} else { } else {
// TODO: // TODO:
} }
}; };
hierarchyPostUpdateHandler = [&](std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) { hierarchyPostUpdateHandler = [&](std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
if (newParent.has_value()) endInsertRows(); if (newParent) endInsertRows();
if (oldParent.has_value()) endRemoveRows(); if (oldParent) endRemoveRows();
}; };
} }
@ -65,10 +65,10 @@ QModelIndex ExplorerModel::index(int row, int column, const QModelIndex &parent)
} }
QModelIndex ExplorerModel::toIndex(std::shared_ptr<Instance> item) { QModelIndex ExplorerModel::toIndex(std::shared_ptr<Instance> item) {
if (item == rootItem || !item->GetParent().has_value()) if (item == rootItem || !item->GetParent())
return {}; return {};
std::shared_ptr<Instance> parentItem = item->GetParent().value(); std::shared_ptr<Instance> parentItem = item->GetParent();
// Check above ensures this item is not root, so value() must be valid // Check above ensures this item is not root, so value() must be valid
for (size_t i = 0; i < parentItem->GetChildren().size(); i++) for (size_t i = 0; i < parentItem->GetChildren().size(); i++)
if (parentItem->GetChildren()[i] == item) if (parentItem->GetChildren()[i] == item)
@ -86,13 +86,13 @@ QModelIndex ExplorerModel::parent(const QModelIndex &index) const {
Instance* childItem = static_cast<Instance*>(index.internalPointer()); Instance* childItem = static_cast<Instance*>(index.internalPointer());
// NORISK: The parent must exist if the child was obtained from it during this frame // NORISK: The parent must exist if the child was obtained from it during this frame
std::shared_ptr<Instance> parentItem = childItem->GetParent().value(); std::shared_ptr<Instance> parentItem = childItem->GetParent();
if (parentItem == rootItem) if (parentItem == rootItem)
return {}; return {};
// Check above ensures this item is not root, so value() must be valid // Check above ensures this item is not root, so value() must be valid
std::shared_ptr<Instance> parentParent = parentItem->GetParent().value(); std::shared_ptr<Instance> parentParent = parentItem->GetParent();
for (size_t i = 0; i < parentParent->GetChildren().size(); i++) for (size_t i = 0; i < parentParent->GetChildren().size(); i++)
if (parentParent->GetChildren()[i] == parentItem) if (parentParent->GetChildren()[i] == parentItem)
return createIndex(i, 0, parentItem.get()); return createIndex(i, 0, parentItem.get());
@ -241,7 +241,7 @@ bool ExplorerModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
UndoState historyState; UndoState historyState;
std::shared_ptr<Instance> parentInst = fromIndex(parent); std::shared_ptr<Instance> parentInst = fromIndex(parent);
for (std::shared_ptr<Instance> instance : slot->instances) { for (std::shared_ptr<Instance> instance : slot->instances) {
historyState.push_back(UndoStateInstanceReparented { instance, instance->GetParent().value_or(nullptr), parentInst }); historyState.push_back(UndoStateInstanceReparented { instance, instance->GetParent(), parentInst });
instance->SetParent(parentInst); instance->SetParent(parentInst);
} }

View file

@ -333,11 +333,11 @@ void PropertiesView::drawBranches(QPainter *painter, const QRect &rect, const QM
QTreeWidget::drawBranches(painter, rect, index); QTreeWidget::drawBranches(painter, rect, index);
} }
void PropertiesView::setSelected(std::optional<std::shared_ptr<Instance>> instance) { void PropertiesView::setSelected(nullable std::shared_ptr<Instance> instance) {
clear(); clear();
currentInstance = {}; currentInstance = {};
if (!instance) return; if (!instance) return;
std::shared_ptr<Instance> inst = instance.value(); std::shared_ptr<Instance> inst = instance;
currentInstance = inst; currentInstance = inst;
std::map<PropertyCategory, QTreeWidgetItem*> propertyCategories; std::map<PropertyCategory, QTreeWidgetItem*> propertyCategories;

View file

@ -31,5 +31,5 @@ public:
void init(); void init();
void setSelected(std::optional<std::shared_ptr<Instance>> instance); void setSelected(nullable std::shared_ptr<Instance> instance);
}; };

View file

@ -70,7 +70,7 @@ void PlaceDocument::updateSelectionListeners(std::shared_ptr<Selection> selectio
selectionConnection = selection->SelectionChanged->Connect([selection, mainWnd](std::vector<Variant> _){ selectionConnection = selection->SelectionChanged->Connect([selection, mainWnd](std::vector<Variant> _){
// Update properties // Update properties
if (selection->Get().size() != 1) if (selection->Get().size() != 1)
mainWnd->ui->propertiesView->setSelected(std::nullopt); mainWnd->ui->propertiesView->setSelected(nullptr);
else else
mainWnd->ui->propertiesView->setSelected(selection->Get()[0]); mainWnd->ui->propertiesView->setSelected(selection->Get()[0]);

View file

@ -27,7 +27,7 @@ void UndoHistory::Undo() {
// The old value used to be valid, so it still should be... // The old value used to be valid, so it still should be...
v->affectedInstance->SetProperty(v->property, v->oldValue).expect(); v->affectedInstance->SetProperty(v->property, v->oldValue).expect();
} else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) {
v->instance->SetParent(std::nullopt); v->instance->SetParent(nullptr);
} else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) {
v->instance->SetParent(v->oldParent); v->instance->SetParent(v->oldParent);
} else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) {
@ -57,7 +57,7 @@ void UndoHistory::Redo() {
} else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceCreated>(&change)) {
v->instance->SetParent(v->newParent); v->instance->SetParent(v->newParent);
} else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceRemoved>(&change)) {
v->instance->SetParent(std::nullopt); v->instance->SetParent(nullptr);
} else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) { } else if (auto v = std::get_if<UndoStateInstanceReparented>(&change)) {
v->instance->SetParent(v->newParent); v->instance->SetParent(v->newParent);
} else if (auto v = std::get_if<UndoStateSelectionChanged>(&change)) { } else if (auto v = std::get_if<UndoStateSelectionChanged>(&change)) {