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>
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, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<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)> HierarchyPostUpdateHandler;
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, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent)> HierarchyPostUpdateHandler;
typedef std::function<void(std::shared_ptr<Instance> instance, std::string property, Variant newValue)> PropertyUpdateHandler;
// TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS

View file

@ -151,9 +151,9 @@ static int inst_index(lua_State* L) {
}
// Look for child
std::optional<std::shared_ptr<Instance>> child = inst->FindFirstChild(key);
nullable std::shared_ptr<Instance> child = inst->FindFirstChild(key);
if (child) {
InstanceRef(child.value()).PushLuaValue(L);
InstanceRef(child).PushLuaValue(L);
return 1;
}
@ -173,7 +173,7 @@ static int inst_newindex(lua_State* L) {
if (meta->flags & PROP_READONLY)
return luaL_error(L, "'%s' of %s is read-only", key.c_str(), inst->GetClass()->className.c_str());
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!!
result<Variant, LuaCastError> value = meta->type.descriptor->fromLuaValue(L, -1);

View file

@ -44,21 +44,16 @@ Instance::Instance(const InstanceType* type) {
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
bool Instance::ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent) {
for (std::optional<std::shared_ptr<Instance>> currentParent = newParent; currentParent.has_value(); currentParent = currentParent.value()->GetParent()) {
if (currentParent.value() == this->shared_from_this())
bool Instance::ancestryContinuityCheck(nullable std::shared_ptr<Instance> newParent) {
for (std::shared_ptr<Instance> currentParent = newParent; currentParent != nullptr; currentParent = currentParent->GetParent()) {
if (currentParent == this->shared_from_this())
return false;
}
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))
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()));
}
// Add ourselves to the new parent
if (newParent.has_value()) {
newParent.value()->children.push_back(this->shared_from_this());
if (newParent != nullptr) {
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: Yeahhh maybe this isn't the best way of doing this?
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;
}
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 oldWorkspace = _workspace;
// Update parent data model and workspace, if applicable
if (GetParent()) {
this->_dataModel = GetParent().value()->GetClass() == &DataModel::TYPE ? std::dynamic_pointer_cast<DataModel>(GetParent().value()) : GetParent().value()->_dataModel;
this->_workspace = GetParent().value()->GetClass() == &Workspace::TYPE ? std::dynamic_pointer_cast<Workspace>(GetParent().value()) : GetParent().value()->_workspace;
if (GetParent() != nullptr) {
this->_dataModel = GetParent()->GetClass() == &DataModel::TYPE ? std::dynamic_pointer_cast<DataModel>(GetParent()) : GetParent()->_dataModel;
this->_workspace = GetParent()->GetClass() == &Workspace::TYPE ? std::dynamic_pointer_cast<Workspace>(GetParent()) : GetParent()->_workspace;
} else {
this->_dataModel = {};
this->_workspace = {};
}
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
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
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
@ -117,23 +112,22 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
}
}
std::optional<std::shared_ptr<DataModel>> Instance::dataModel() {
return (_dataModel.expired()) ? std::nullopt : std::make_optional(_dataModel.lock());
nullable std::shared_ptr<DataModel> Instance::dataModel() {
return _dataModel.expired() ? nullptr : _dataModel.lock();
}
std::optional<std::shared_ptr<Workspace>> Instance::workspace() {
return (_workspace.expired()) ? std::nullopt : std::make_optional(_workspace.lock());
nullable std::shared_ptr<Workspace> Instance::workspace() {
return _workspace.expired() ? nullptr : _workspace.lock();
}
std::optional<std::shared_ptr<Instance>> Instance::GetParent() {
if (parent.expired()) return std::nullopt;
return parent.lock();
nullable std::shared_ptr<Instance> Instance::GetParent() {
return parent.expired() ? nullptr : parent.lock();
}
void Instance::Destroy() {
if (parentLocked) return;
// TODO: Implement proper distruction stuff
SetParent(std::nullopt);
SetParent(nullptr);
parentLocked = true;
}
@ -143,12 +137,12 @@ bool Instance::IsA(std::string className) {
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) {
if (child->name == name)
return child;
}
return std::nullopt;
return nullptr;
}
static std::shared_ptr<Instance> DUMMY_INSTANCE;
@ -164,15 +158,15 @@ bool Instance::IsParentLocked() {
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
}
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
}
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
}
@ -230,7 +224,7 @@ fallible<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyVa
this->name = (std::string)value.get<std::string>();
} else if (name == "Parent") {
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") {
return AssignToReadOnlyMember(GetClass()->className, name);
} 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
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();
current = current->GetParent().value();
current = current->GetParent();
// But not if one up is null or the root element
if (!current->GetParent() || current == root) {
@ -443,12 +437,12 @@ DescendantsIterator::self_type DescendantsIterator::operator++(int _) {
// Now move to the next sibling
siblingIndex.back()++;
current = current->GetParent().value()->GetChildren()[siblingIndex.back()];
current = current->GetParent()->GetChildren()[siblingIndex.back()];
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>();
std::shared_ptr<Instance> newInstance = GetClass()->constructor();
@ -494,9 +488,9 @@ std::optional<std::shared_ptr<Instance>> Instance::Clone(RefStateClone state) {
// Clone children
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)
newInstance->AddChild(clonedChild.value());
newInstance->AddChild(clonedChild);
}
return newInstance;
@ -521,12 +515,12 @@ std::vector<std::pair<std::string, std::shared_ptr<Instance>>> Instance::GetRefe
std::string Instance::GetFullName() {
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")) {
currentName = currentParent.value()->name + "." + currentName;
while (currentParent && !currentParent->IsA("DataModel")) {
currentName = currentParent->name + "." + currentName;
currentParent = currentParent.value()->GetParent();
currentParent = currentParent->GetParent();
}
return currentName;

View file

@ -16,6 +16,7 @@
#include "error/result.h"
#include "member.h"
#include "objects/base/refstate.h"
#include "utils.h"
class Instance;
typedef std::shared_ptr<Instance>(*InstanceConstructor)();
@ -59,8 +60,8 @@ private:
std::weak_ptr<DataModel> _dataModel;
std::weak_ptr<Workspace> _workspace;
bool ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent);
void updateAncestry(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);
bool ancestryContinuityCheck(nullable 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
protected:
@ -75,17 +76,17 @@ protected:
virtual void InternalUpdateProperty(std::string name);
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 OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);
virtual void OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace);
virtual void OnParentUpdated(nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent);
virtual void OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent);
virtual void OnWorkspaceAdded(nullable std::shared_ptr<Workspace> oldWorkspace, std::shared_ptr<Workspace> newWorkspace);
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace);
// 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
// NOTE: This value is not necessarily present if dataModel is present
// 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:
const static InstanceType TYPE;
std::string name;
@ -96,8 +97,8 @@ public:
// Instance is abstract, so it should not implement GetClass directly
virtual const InstanceType* GetClass() = 0;
static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
std::optional<std::shared_ptr<Instance>> GetParent();
bool SetParent(nullable std::shared_ptr<Instance> newParent);
nullable std::shared_ptr<Instance> GetParent();
bool IsParentLocked();
inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; }
void Destroy();
@ -111,7 +112,7 @@ public:
DescendantsIterator GetDescendantsEnd();
// Utility functions
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();
// Properties
@ -136,7 +137,7 @@ public:
// Serialization
void Serialize(pugi::xml_node parent, RefStateSerialize 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
@ -158,7 +159,7 @@ public:
self_type operator++(int _);
private:
std::optional<std::shared_ptr<Instance>> root;
nullable std::shared_ptr<Instance> root;
std::shared_ptr<Instance> current;
std::vector<int> siblingIndex;
};

View file

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

View file

@ -13,7 +13,7 @@ protected:
virtual void InitService();
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;
};

View file

@ -107,14 +107,14 @@ result<std::shared_ptr<Service>, NoSuchService> DataModel::GetService(std::strin
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) {
return NoSuchService(className);
}
if (services.count(className) != 0)
return std::make_optional(std::dynamic_pointer_cast<Service>(services[className]));
return (std::optional<std::shared_ptr<Service>>)std::nullopt;
return std::dynamic_pointer_cast<Service>(services[className]);
return nullptr;
}
std::shared_ptr<DataModel> DataModel::CloneModel() {
@ -166,11 +166,11 @@ std::shared_ptr<DataModel> DataModel::CloneModel() {
if (!result)
continue;
newModel->AddChild(result.value());
newModel->AddChild(result);
// Special case: Ignore instances parented to DataModel which are not services
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>(); };
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>
std::shared_ptr<T> GetService() {
@ -38,10 +38,10 @@ public:
}
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");
if (!result) return std::nullopt;
return std::dynamic_pointer_cast<T>(result.value());
if (!result) return nullptr;
return std::dynamic_pointer_cast<T>(result);
}
// Saving/loading

View file

@ -17,7 +17,7 @@ JointInstance::JointInstance(const InstanceType* type): Instance(type) {
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
breakJoint();
@ -54,6 +54,6 @@ void JointInstance::onUpdated(std::string property) {
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();
}

View file

@ -23,9 +23,9 @@ protected:
// The workspace the joint was created in, if it exists
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);
virtual void buildJoint() = 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;
// 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
// 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;
// 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

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;
// 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
// 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;
// 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
// used to be rather than specifying an anchor rotation, so whatever.

View file

@ -14,7 +14,6 @@
#include "objects/joint/snap.h"
#include "rendering/renderer.h"
#include "enum/surface.h"
#include <cstdio>
#include <glm/common.hpp>
#include <memory>
#include <optional>
@ -28,18 +27,18 @@ BasePart::BasePart(const InstanceType* type, PartConstructParams params): PVInst
BasePart::~BasePart() {
// This relies on physicsCommon still existing. Be very careful.
if (this->rigidBody && workspace()) {
workspace().value()->RemoveBody(shared<BasePart>());
if (this->rigidBody && workspace() != nullptr) {
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)
this->rigidBody->setIsActive(workspace().has_value());
this->rigidBody->setIsActive(workspace() != nullptr);
if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
if (workspace() != nullptr)
workspace()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
// Destroy joints
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
}
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>());
}
@ -58,8 +57,8 @@ void BasePart::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
void BasePart::onUpdated(std::string property) {
bool reset = property == "Position" || property == "Rotation" || property == "CFrame" || property == "Size" || property == "Shape";
if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
if (workspace() != nullptr)
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
if (reset)
@ -204,7 +203,7 @@ bool BasePart::checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3
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::Studs && (b == SurfaceType::Inlet || 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();
if (a == SurfaceType::Motor)
return RotateV::New();
return std::nullopt;
return nullptr;
}
void BasePart::MakeJoints() {
@ -229,7 +228,7 @@ void BasePart::MakeJoints() {
// TEMPORARY
// 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;
if (obj == shared_from_this()) continue; // Skip ourselves
if (!obj->IsA<BasePart>()) continue;
@ -276,12 +275,12 @@ void BasePart::MakeJoints() {
auto joint_ = makeJointFromSurfaces(mySurface, otherSurface);
if (!joint_) continue;
std::shared_ptr<JointInstance> joint = joint_.value();
std::shared_ptr<JointInstance> joint = joint_;
joint->part0 = shared<BasePart>();
joint->part1 = otherPart->shared<BasePart>();
joint->c0 = contact0;
joint->c1 = contact1;
dataModel().value()->GetService<JointsService>()->AddChild(joint);
dataModel()->GetService<JointsService>()->AddChild(joint);
joint->UpdateProperty("Part0");
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 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;
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);
virtual void updateCollider(rp::PhysicsCommon* common) = 0;

View file

@ -23,7 +23,7 @@ Script::~Script() {
}
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;
int top = lua_gettop(L);

View file

@ -18,8 +18,8 @@ void JointsService::InitService() {
}
}
std::optional<std::shared_ptr<Workspace>> JointsService::jointWorkspace() {
if (!dataModel()) return std::nullopt;
nullable std::shared_ptr<Workspace> JointsService::jointWorkspace() {
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 {
AUTOGEN_PREAMBLE
private:
std::optional<std::shared_ptr<Workspace>> jointWorkspace();
nullable std::shared_ptr<Workspace> jointWorkspace();
protected:
void InitService() override;
bool initialized = false;

View file

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

View file

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

View file

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

View file

@ -412,9 +412,9 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
// Traverse to the root model
if (~evt->modifiers() & Qt::AltModifier) {
std::optional<std::shared_ptr<Instance>> nextParent = selObject->GetParent();
while (nextParent.value() && nextParent.value()->IsA("Model")) {
selObject = std::dynamic_pointer_cast<PVInstance>(nextParent.value()); nextParent = selObject->GetParent();
nullable std::shared_ptr<Instance> nextParent = selObject->GetParent();
while (nextParent && nextParent->IsA("Model")) {
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>();
for (std::weak_ptr<Instance> inst : selection->Get()) {
if (inst.expired()) continue;
historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent().value() });
inst.lock()->SetParent(std::nullopt);
historyState.push_back(UndoStateInstanceRemoved { inst.lock(), inst.lock()->GetParent() });
inst.lock()->SetParent(nullptr);
}
selection->Set({});
historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}});
@ -433,9 +433,9 @@ void MainWindow::connectActionHandlers() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) {
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()->SetParent(std::nullopt);
inst.lock()->SetParent(nullptr);
}
selection->Set({});
historyState.push_back(UndoStateSelectionChanged {selection->Get(), {}});
@ -502,8 +502,8 @@ void MainWindow::connectActionHandlers() {
bool done = false;
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (auto object : selection->Get()) {
if (firstParent == nullptr && object->GetParent().has_value()) firstParent = object->GetParent().value();
historyState.push_back(UndoStateInstanceReparented { object, object->GetParent().value(), model });
if (!firstParent && object->GetParent() != nullptr) firstParent = object->GetParent();
historyState.push_back(UndoStateInstanceReparented { object, object->GetParent(), model });
object->SetParent(model);
done = true;
}
@ -535,13 +535,13 @@ void MainWindow::connectActionHandlers() {
done = true;
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());
newSelection.push_back(object);
}
historyState.push_back(UndoStateInstanceRemoved { model, model->GetParent().value() });
model->SetParent(std::nullopt);
historyState.push_back(UndoStateInstanceRemoved { model, model->GetParent() });
model->SetParent(nullptr);
}
if (!done)

View file

@ -22,24 +22,24 @@ ExplorerModel::ExplorerModel(std::shared_ptr<Instance> dataRoot, QWidget *parent
: QAbstractItemModel(parent)
, rootItem(dataRoot) {
// 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) {
if (oldParent.has_value()) {
auto children = oldParent.value()->GetChildren();
hierarchyPreUpdateHandler = [&](std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
if (oldParent) {
auto children = oldParent->GetChildren();
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()) {
size_t size = newParent.value()->GetChildren().size();
beginInsertRows(toIndex(newParent.value()), size, size);
if (newParent) {
size_t size = newParent->GetChildren().size();
beginInsertRows(toIndex(newParent), size, size);
} else {
// TODO:
}
};
hierarchyPostUpdateHandler = [&](std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) {
if (newParent.has_value()) endInsertRows();
if (oldParent.has_value()) endRemoveRows();
hierarchyPostUpdateHandler = [&](std::shared_ptr<Instance> object, nullable std::shared_ptr<Instance> oldParent, nullable std::shared_ptr<Instance> newParent) {
if (newParent) endInsertRows();
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) {
if (item == rootItem || !item->GetParent().has_value())
if (item == rootItem || !item->GetParent())
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
for (size_t i = 0; i < parentItem->GetChildren().size(); i++)
if (parentItem->GetChildren()[i] == item)
@ -86,13 +86,13 @@ QModelIndex ExplorerModel::parent(const QModelIndex &index) const {
Instance* childItem = static_cast<Instance*>(index.internalPointer());
// 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)
return {};
// 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++)
if (parentParent->GetChildren()[i] == parentItem)
return createIndex(i, 0, parentItem.get());
@ -241,7 +241,7 @@ bool ExplorerModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
UndoState historyState;
std::shared_ptr<Instance> parentInst = fromIndex(parent);
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);
}

View file

@ -333,11 +333,11 @@ void PropertiesView::drawBranches(QPainter *painter, const QRect &rect, const QM
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();
currentInstance = {};
if (!instance) return;
std::shared_ptr<Instance> inst = instance.value();
std::shared_ptr<Instance> inst = instance;
currentInstance = inst;
std::map<PropertyCategory, QTreeWidgetItem*> propertyCategories;

View file

@ -31,5 +31,5 @@ public:
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> _){
// Update properties
if (selection->Get().size() != 1)
mainWnd->ui->propertiesView->setSelected(std::nullopt);
mainWnd->ui->propertiesView->setSelected(nullptr);
else
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...
v->affectedInstance->SetProperty(v->property, v->oldValue).expect();
} 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)) {
v->instance->SetParent(v->oldParent);
} 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)) {
v->instance->SetParent(v->newParent);
} 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)) {
v->instance->SetParent(v->newParent);
} else if (auto v = std::get_if<UndoStateSelectionChanged>(&change)) {