refactor(joint): abstracted jointinstance into its own class away from snap
This commit is contained in:
parent
587629fcdd
commit
6a461143a4
13 changed files with 219 additions and 158 deletions
|
@ -148,6 +148,12 @@ void Instance::Destroy() {
|
||||||
parentLocked = true;
|
parentLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Instance::IsA(std::string className) {
|
||||||
|
const InstanceType* cur = GetClass();
|
||||||
|
while (cur && cur->className != className) { cur = cur->super; }
|
||||||
|
return cur != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Instance> DUMMY_INSTANCE;
|
static std::shared_ptr<Instance> DUMMY_INSTANCE;
|
||||||
DescendantsIterator Instance::GetDescendantsStart() {
|
DescendantsIterator Instance::GetDescendantsStart() {
|
||||||
return DescendantsIterator(GetChildren().size() > 0 ? GetChildren()[0] : DUMMY_INSTANCE);
|
return DescendantsIterator(GetChildren().size() > 0 ? GetChildren()[0] : DUMMY_INSTANCE);
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct InstanceType {
|
||||||
typedef std::pair<std::shared_ptr<Instance>, std::string> _RefStatePropertyCell;
|
typedef std::pair<std::shared_ptr<Instance>, std::string> _RefStatePropertyCell;
|
||||||
|
|
||||||
class DescendantsIterator;
|
class DescendantsIterator;
|
||||||
class Snap;
|
class JointInstance;
|
||||||
|
|
||||||
// Base class for all instances in the data model
|
// Base class for all instances in the data model
|
||||||
// Note: enable_shared_from_this HAS to be public or else its field will not be populated
|
// Note: enable_shared_from_this HAS to be public or else its field will not be populated
|
||||||
|
@ -60,7 +60,7 @@ private:
|
||||||
bool ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent);
|
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);
|
void updateAncestry(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);
|
||||||
|
|
||||||
friend Snap; // This isn't ideal, but oh well
|
friend JointInstance; // This isn't ideal, but oh well
|
||||||
protected:
|
protected:
|
||||||
bool parentLocked = false;
|
bool parentLocked = false;
|
||||||
std::unique_ptr<MemberMap> memberMap;
|
std::unique_ptr<MemberMap> memberMap;
|
||||||
|
@ -92,6 +92,9 @@ public:
|
||||||
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();
|
||||||
|
// Determines whether this object is an instance of, or an instance of a subclass of the sepcified type's class name
|
||||||
|
bool IsA(std::string className);
|
||||||
|
template <typename T> bool IsA() { return IsA(T::TYPE.className); }
|
||||||
|
|
||||||
DescendantsIterator GetDescendantsStart();
|
DescendantsIterator GetDescendantsStart();
|
||||||
DescendantsIterator GetDescendantsEnd();
|
DescendantsIterator GetDescendantsEnd();
|
||||||
|
|
94
core/src/objects/joint/jointinstance.cpp
Normal file
94
core/src/objects/joint/jointinstance.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "jointinstance.h"
|
||||||
|
|
||||||
|
#include "datatypes/cframe.h"
|
||||||
|
#include "datatypes/ref.h"
|
||||||
|
#include "objects/datamodel.h"
|
||||||
|
#include "objects/jointsservice.h"
|
||||||
|
#include "objects/part.h"
|
||||||
|
#include "objects/workspace.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <reactphysics3d/constraint/FixedJoint.h>
|
||||||
|
#include <reactphysics3d/engine/PhysicsWorld.h>
|
||||||
|
#include "ptr_helpers.h"
|
||||||
|
|
||||||
|
const InstanceType JointInstance::TYPE = {
|
||||||
|
.super = &Instance::TYPE,
|
||||||
|
.className = "JointInstance",
|
||||||
|
};
|
||||||
|
|
||||||
|
const InstanceType* JointInstance::GetClass() {
|
||||||
|
return &TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JointInstance::JointInstance(const InstanceType* type): Instance(type) {
|
||||||
|
this->memberMap = std::make_unique<MemberMap>(MemberMap {
|
||||||
|
.super = std::move(this->memberMap),
|
||||||
|
.members = {
|
||||||
|
{ "Part0", {
|
||||||
|
.backingField = &part0,
|
||||||
|
.type = &Data::InstanceRef::TYPE,
|
||||||
|
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
|
||||||
|
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
|
||||||
|
}}, { "Part1", {
|
||||||
|
.backingField = &part1,
|
||||||
|
.type = &Data::InstanceRef::TYPE,
|
||||||
|
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
|
||||||
|
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
|
||||||
|
}}, { "C0", {
|
||||||
|
.backingField = &c0,
|
||||||
|
.type = &Data::CFrame::TYPE,
|
||||||
|
.codec = fieldCodecOf<Data::CFrame>(),
|
||||||
|
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
|
||||||
|
}}, { "C1", {
|
||||||
|
.backingField = &c1,
|
||||||
|
.type = &Data::CFrame::TYPE,
|
||||||
|
.codec = fieldCodecOf<Data::CFrame>(),
|
||||||
|
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
JointInstance::~JointInstance() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void JointInstance::OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) {
|
||||||
|
// Destroy and rebuild the joint, it's the simplest solution that actually works
|
||||||
|
|
||||||
|
breakJoint();
|
||||||
|
buildJoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JointInstance::onUpdated(std::string property) {
|
||||||
|
// Add ourselves to the attached parts, or remove, if applicable
|
||||||
|
|
||||||
|
// Parts differ, delete
|
||||||
|
if (part0 != oldPart0 && !oldPart0.expired()) {
|
||||||
|
oldPart0.lock()->untrackJoint(shared<JointInstance>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part1 != oldPart1 && !oldPart1.expired()) {
|
||||||
|
oldPart1.lock()->untrackJoint(shared<JointInstance>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parts differ, add
|
||||||
|
if (part0 != oldPart0 && !part0.expired()) {
|
||||||
|
part0.lock()->trackJoint(shared<JointInstance>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part1 != oldPart1 && !part1.expired()) {
|
||||||
|
part1.lock()->trackJoint(shared<JointInstance>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy and rebuild the joint, if applicable
|
||||||
|
|
||||||
|
breakJoint();
|
||||||
|
buildJoint();
|
||||||
|
|
||||||
|
oldPart0 = part0;
|
||||||
|
oldPart1 = part1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<Workspace>> JointInstance::workspaceOfPart(std::shared_ptr<Part> part) {
|
||||||
|
return part->workspace();
|
||||||
|
}
|
|
@ -7,20 +7,19 @@
|
||||||
class Part;
|
class Part;
|
||||||
class Workspace;
|
class Workspace;
|
||||||
|
|
||||||
class Snap : public Instance {
|
class JointInstance : public Instance {
|
||||||
rp::FixedJoint* joint = nullptr;
|
|
||||||
|
|
||||||
std::weak_ptr<Part> oldPart0;
|
std::weak_ptr<Part> oldPart0;
|
||||||
std::weak_ptr<Part> oldPart1;
|
std::weak_ptr<Part> oldPart1;
|
||||||
|
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;
|
||||||
protected:
|
|
||||||
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) override;
|
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) override;
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<Workspace>> workspaceOfPart(std::shared_ptr<Part>);
|
||||||
void onUpdated(std::string property);
|
void onUpdated(std::string property);
|
||||||
void buildJoint();
|
virtual void buildJoint() = 0;
|
||||||
void breakJoint();
|
virtual void breakJoint() = 0;
|
||||||
public:
|
public:
|
||||||
const static InstanceType TYPE;
|
const static InstanceType TYPE;
|
||||||
|
|
||||||
|
@ -29,10 +28,8 @@ public:
|
||||||
Data::CFrame c0;
|
Data::CFrame c0;
|
||||||
Data::CFrame c1;
|
Data::CFrame c1;
|
||||||
|
|
||||||
Snap();
|
JointInstance(const InstanceType*);
|
||||||
~Snap();
|
~JointInstance();
|
||||||
|
|
||||||
static inline std::shared_ptr<Snap> New() { return std::make_shared<Snap>(); };
|
|
||||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Snap>(); };
|
|
||||||
virtual const InstanceType* GetClass() override;
|
virtual const InstanceType* GetClass() override;
|
||||||
};
|
};
|
59
core/src/objects/joint/snap.cpp
Normal file
59
core/src/objects/joint/snap.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "snap.h"
|
||||||
|
|
||||||
|
#include "datatypes/cframe.h"
|
||||||
|
#include "objects/datamodel.h"
|
||||||
|
#include "objects/joint/jointinstance.h"
|
||||||
|
#include "objects/jointsservice.h"
|
||||||
|
#include "objects/part.h"
|
||||||
|
#include "objects/workspace.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <reactphysics3d/constraint/FixedJoint.h>
|
||||||
|
#include <reactphysics3d/engine/PhysicsWorld.h>
|
||||||
|
|
||||||
|
const InstanceType Snap::TYPE = {
|
||||||
|
.super = &JointInstance::TYPE,
|
||||||
|
.className = "Snap",
|
||||||
|
.constructor = &Snap::Create,
|
||||||
|
};
|
||||||
|
|
||||||
|
const InstanceType* Snap::GetClass() {
|
||||||
|
return &TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Snap::Snap(): JointInstance(&TYPE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Snap::~Snap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Snap::buildJoint() {
|
||||||
|
// Only if both parts are set, are not the same part, are part of a workspace, and are part of the same workspace, we build the joint
|
||||||
|
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;
|
||||||
|
|
||||||
|
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
||||||
|
if (!workspace->physicsWorld) return;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
Data::CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
|
||||||
|
part1.lock()->cframe = newFrame;
|
||||||
|
workspace->SyncPartPhysics(part1.lock());
|
||||||
|
|
||||||
|
// printf("c1.Rotation: ");
|
||||||
|
// printVec(c1.ToEulerAnglesXYZ());
|
||||||
|
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
||||||
|
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
||||||
|
jointWorkspace = workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
||||||
|
void Snap::breakJoint() {
|
||||||
|
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
||||||
|
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
||||||
|
|
||||||
|
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
||||||
|
this->joint = nullptr;
|
||||||
|
}
|
25
core/src/objects/joint/snap.h
Normal file
25
core/src/objects/joint/snap.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "objects/base/instance.h"
|
||||||
|
#include "objects/joint/jointinstance.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class Part;
|
||||||
|
class Workspace;
|
||||||
|
|
||||||
|
class Snap : public JointInstance {
|
||||||
|
rp::FixedJoint* joint = nullptr;
|
||||||
|
|
||||||
|
virtual void buildJoint() override;
|
||||||
|
virtual void breakJoint() override;
|
||||||
|
public:
|
||||||
|
const static InstanceType TYPE;
|
||||||
|
|
||||||
|
Snap();
|
||||||
|
~Snap();
|
||||||
|
|
||||||
|
static inline std::shared_ptr<Snap> New() { return std::make_shared<Snap>(); };
|
||||||
|
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Snap>(); };
|
||||||
|
virtual const InstanceType* GetClass() override;
|
||||||
|
};
|
|
@ -2,12 +2,9 @@
|
||||||
|
|
||||||
#include "objects/base/service.h"
|
#include "objects/base/service.h"
|
||||||
|
|
||||||
class Snap;
|
|
||||||
class JointsService : public Service {
|
class JointsService : public Service {
|
||||||
private:
|
private:
|
||||||
std::optional<std::shared_ptr<Workspace>> jointWorkspace();
|
std::optional<std::shared_ptr<Workspace>> jointWorkspace();
|
||||||
|
|
||||||
friend Snap;
|
|
||||||
protected:
|
protected:
|
||||||
void InitService() override;
|
void InitService() override;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
|
#include "objects/joint/jointinstance.h"
|
||||||
#include "objects/jointsservice.h"
|
#include "objects/jointsservice.h"
|
||||||
#include "objects/part.h"
|
#include "objects/part.h"
|
||||||
#include "objects/snap.h"
|
#include "objects/joint/snap.h"
|
||||||
#include "objects/workspace.h"
|
#include "objects/workspace.h"
|
||||||
|
|
||||||
std::map<std::string, const InstanceType*> INSTANCE_MAP = {
|
std::map<std::string, const InstanceType*> INSTANCE_MAP = {
|
||||||
|
@ -10,5 +11,6 @@ std::map<std::string, const InstanceType*> INSTANCE_MAP = {
|
||||||
{ "Workspace", &Workspace::TYPE },
|
{ "Workspace", &Workspace::TYPE },
|
||||||
{ "DataModel", &DataModel::TYPE },
|
{ "DataModel", &DataModel::TYPE },
|
||||||
{ "Snap", &Snap::TYPE },
|
{ "Snap", &Snap::TYPE },
|
||||||
|
{ "JointInstance", &JointInstance::TYPE },
|
||||||
{ "JointsService", &JointsService::TYPE },
|
{ "JointsService", &JointsService::TYPE },
|
||||||
};
|
};
|
|
@ -7,7 +7,8 @@
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "objects/base/member.h"
|
#include "objects/base/member.h"
|
||||||
#include "objects/jointsservice.h"
|
#include "objects/jointsservice.h"
|
||||||
#include "objects/snap.h"
|
#include "objects/joint/jointinstance.h"
|
||||||
|
#include "objects/joint/snap.h"
|
||||||
#include "rendering/surface.h"
|
#include "rendering/surface.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -227,12 +228,12 @@ Vector3 Part::GetAABB() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::BreakJoints() {
|
void Part::BreakJoints() {
|
||||||
for (std::weak_ptr<Snap> joint : primaryJoints) {
|
for (std::weak_ptr<JointInstance> joint : primaryJoints) {
|
||||||
if (joint.expired()) continue;
|
if (joint.expired()) continue;
|
||||||
joint.lock()->Destroy();
|
joint.lock()->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::weak_ptr<Snap> joint : secondaryJoints) {
|
for (std::weak_ptr<JointInstance> joint : secondaryJoints) {
|
||||||
if (joint.expired()) continue;
|
if (joint.expired()) continue;
|
||||||
joint.lock()->Destroy();
|
joint.lock()->Destroy();
|
||||||
}
|
}
|
||||||
|
@ -335,7 +336,7 @@ void Part::MakeJoints() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::trackJoint(std::shared_ptr<Snap> joint) {
|
void Part::trackJoint(std::shared_ptr<JointInstance> joint) {
|
||||||
if (!joint->part0.expired() && joint->part0.lock() == shared_from_this()) {
|
if (!joint->part0.expired() && joint->part0.lock() == shared_from_this()) {
|
||||||
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
|
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
|
||||||
// Clean expired refs
|
// Clean expired refs
|
||||||
|
@ -369,7 +370,7 @@ void Part::trackJoint(std::shared_ptr<Snap> joint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::untrackJoint(std::shared_ptr<Snap> joint) {
|
void Part::untrackJoint(std::shared_ptr<JointInstance> joint) {
|
||||||
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
|
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
|
||||||
// Clean expired refs
|
// Clean expired refs
|
||||||
if (it->expired() || it->lock() == joint) {
|
if (it->expired() || it->lock() == joint) {
|
||||||
|
|
|
@ -29,17 +29,17 @@ class Snap;
|
||||||
class Part : public Instance {
|
class Part : public Instance {
|
||||||
protected:
|
protected:
|
||||||
// Joints where this part is Part0
|
// Joints where this part is Part0
|
||||||
std::vector<std::weak_ptr<Snap>> primaryJoints;
|
std::vector<std::weak_ptr<JointInstance>> primaryJoints;
|
||||||
// Joints where this part is Part1
|
// Joints where this part is Part1
|
||||||
std::vector<std::weak_ptr<Snap>> secondaryJoints;
|
std::vector<std::weak_ptr<JointInstance>> secondaryJoints;
|
||||||
|
|
||||||
void trackJoint(std::shared_ptr<Snap>);
|
void trackJoint(std::shared_ptr<JointInstance>);
|
||||||
void untrackJoint(std::shared_ptr<Snap>);
|
void untrackJoint(std::shared_ptr<JointInstance>);
|
||||||
|
|
||||||
SurfaceType surfaceFromFace(NormalId);
|
SurfaceType surfaceFromFace(NormalId);
|
||||||
bool checkJointContinuinty(std::shared_ptr<Part>);
|
bool checkJointContinuinty(std::shared_ptr<Part>);
|
||||||
|
|
||||||
friend Snap;
|
friend JointInstance;
|
||||||
|
|
||||||
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) override;
|
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) override;
|
||||||
void onUpdated(std::string);
|
void onUpdated(std::string);
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
#include "snap.h"
|
|
||||||
|
|
||||||
#include "datatypes/cframe.h"
|
|
||||||
#include "datatypes/ref.h"
|
|
||||||
#include "objects/datamodel.h"
|
|
||||||
#include "objects/jointsservice.h"
|
|
||||||
#include "objects/part.h"
|
|
||||||
#include "workspace.h"
|
|
||||||
#include <memory>
|
|
||||||
#include <reactphysics3d/constraint/FixedJoint.h>
|
|
||||||
#include <reactphysics3d/engine/PhysicsWorld.h>
|
|
||||||
#include "ptr_helpers.h"
|
|
||||||
|
|
||||||
const InstanceType Snap::TYPE = {
|
|
||||||
.super = &Instance::TYPE,
|
|
||||||
.className = "Snap",
|
|
||||||
.constructor = &Snap::Create,
|
|
||||||
};
|
|
||||||
|
|
||||||
const InstanceType* Snap::GetClass() {
|
|
||||||
return &TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Snap::Snap(): Instance(&TYPE) {
|
|
||||||
this->memberMap = std::make_unique<MemberMap>(MemberMap {
|
|
||||||
.super = std::move(this->memberMap),
|
|
||||||
.members = {
|
|
||||||
{ "Part0", {
|
|
||||||
.backingField = &part0,
|
|
||||||
.type = &Data::InstanceRef::TYPE,
|
|
||||||
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
|
|
||||||
.updateCallback = memberFunctionOf(&Snap::onUpdated, this),
|
|
||||||
}}, { "Part1", {
|
|
||||||
.backingField = &part1,
|
|
||||||
.type = &Data::InstanceRef::TYPE,
|
|
||||||
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
|
|
||||||
.updateCallback = memberFunctionOf(&Snap::onUpdated, this),
|
|
||||||
}}, { "C0", {
|
|
||||||
.backingField = &c0,
|
|
||||||
.type = &Data::CFrame::TYPE,
|
|
||||||
.codec = fieldCodecOf<Data::CFrame>(),
|
|
||||||
.updateCallback = memberFunctionOf(&Snap::onUpdated, this),
|
|
||||||
}}, { "C1", {
|
|
||||||
.backingField = &c1,
|
|
||||||
.type = &Data::CFrame::TYPE,
|
|
||||||
.codec = fieldCodecOf<Data::CFrame>(),
|
|
||||||
.updateCallback = memberFunctionOf(&Snap::onUpdated, this),
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Snap::~Snap() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Snap::OnAncestryChanged(std::optional<std::shared_ptr<Instance>>, std::optional<std::shared_ptr<Instance>>) {
|
|
||||||
// Destroy and rebuild the joint, it's the simplest solution that actually works
|
|
||||||
|
|
||||||
breakJoint();
|
|
||||||
buildJoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Snap::onUpdated(std::string property) {
|
|
||||||
// Add ourselves to the attached parts, or remove, if applicable
|
|
||||||
|
|
||||||
// Parts differ, delete
|
|
||||||
if (part0 != oldPart0 && !oldPart0.expired()) {
|
|
||||||
oldPart0.lock()->untrackJoint(shared<Snap>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part1 != oldPart1 && !oldPart1.expired()) {
|
|
||||||
oldPart1.lock()->untrackJoint(shared<Snap>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parts differ, add
|
|
||||||
if (part0 != oldPart0 && !part0.expired()) {
|
|
||||||
part0.lock()->trackJoint(shared<Snap>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part1 != oldPart1 && !part1.expired()) {
|
|
||||||
part1.lock()->trackJoint(shared<Snap>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy and rebuild the joint, if applicable
|
|
||||||
|
|
||||||
breakJoint();
|
|
||||||
buildJoint();
|
|
||||||
|
|
||||||
oldPart0 = part0;
|
|
||||||
oldPart1 = part1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Snap::buildJoint() {
|
|
||||||
// Only if both parts are set, are not the same part, are part of a workspace, and are part of the same workspace, we build the joint
|
|
||||||
if (part0.expired() || part1.expired() || part0.lock() == part1.lock() || !part0.lock()->workspace() || part0.lock()->workspace() != part1.lock()->workspace()) 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;
|
|
||||||
|
|
||||||
std::shared_ptr<Workspace> workspace = part0.lock()->workspace().value();
|
|
||||||
if (!workspace->physicsWorld) return;
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
Data::CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
|
|
||||||
part1.lock()->cframe = newFrame;
|
|
||||||
workspace->SyncPartPhysics(part1.lock());
|
|
||||||
|
|
||||||
// printf("c1.Rotation: ");
|
|
||||||
// printVec(c1.ToEulerAnglesXYZ());
|
|
||||||
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
|
||||||
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
|
||||||
jointWorkspace = workspace;
|
|
||||||
}
|
|
||||||
|
|
||||||
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
|
||||||
void Snap::breakJoint() {
|
|
||||||
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
|
||||||
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
|
||||||
|
|
||||||
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
|
||||||
this->joint = nullptr;
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "objects/jointsservice.h"
|
#include "objects/jointsservice.h"
|
||||||
#include "objects/snap.h"
|
#include "objects/joint/jointinstance.h"
|
||||||
#include "physics/util.h"
|
#include "physics/util.h"
|
||||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ void Workspace::InitService() {
|
||||||
// Sync all parts
|
// Sync all parts
|
||||||
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
||||||
InstanceRef obj = *it;
|
InstanceRef obj = *it;
|
||||||
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
|
if (!obj->IsA<Part>()) continue;
|
||||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
|
std::shared_ptr<Part> part = obj->CastTo<Part>().expect();
|
||||||
this->SyncPartPhysics(part);
|
this->SyncPartPhysics(part);
|
||||||
part->MakeJoints();
|
part->MakeJoints();
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,14 @@ void Workspace::InitService() {
|
||||||
// Activate all joints
|
// Activate all joints
|
||||||
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
||||||
InstanceRef obj = *it;
|
InstanceRef obj = *it;
|
||||||
if (obj->GetClass()->className != "Snap") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
|
if (!obj->IsA<JointInstance>()) continue;
|
||||||
std::shared_ptr<Snap> joint = std::dynamic_pointer_cast<Snap>(obj);
|
std::shared_ptr<JointInstance> joint = obj->CastTo<JointInstance>().expect();
|
||||||
joint->UpdateProperty("Part0");
|
joint->UpdateProperty("Part0");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto obj : dataModel().value()->GetService<JointsService>()->GetChildren()) {
|
for (auto obj : dataModel().value()->GetService<JointsService>()->GetChildren()) {
|
||||||
if (obj->GetClass()->className != "Snap") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
|
if (!obj->IsA<JointInstance>()) continue;
|
||||||
std::shared_ptr<Snap> joint = std::dynamic_pointer_cast<Snap>(obj);
|
std::shared_ptr<JointInstance> joint = obj->CastTo<JointInstance>().expect();
|
||||||
joint->UpdateProperty("Part0");
|
joint->UpdateProperty("Part0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "objects/jointsservice.h"
|
#include "objects/jointsservice.h"
|
||||||
#include "objects/snap.h"
|
#include "objects/joint/snap.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <qclipboard.h>
|
#include <qclipboard.h>
|
||||||
|
|
Loading…
Add table
Reference in a new issue