refactor(part): refactored part into basepart

This commit is contained in:
maelstrom 2025-07-13 18:20:50 +02:00
parent 0196d80944
commit d23206b1fc
27 changed files with 189 additions and 134 deletions

View file

@ -1,6 +1,6 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "objects/part.h"
#include "objects/part/part.h"
#include "rendering/renderer.h"
#include "common.h"
@ -15,7 +15,7 @@ void mouseCallback(GLFWwindow* window, double xpos, double ypos);
void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void resizeCallback(GLFWwindow* window, int width, int height);
std::shared_ptr<Part> lastPart;
std::shared_ptr<BasePart> lastPart;
int main() {
Logger::init();
@ -58,7 +58,7 @@ int main() {
for (std::shared_ptr<Instance> inst : gWorkspace()->GetChildren()) {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
gWorkspace()->SyncPartPhysics(part);
}

View file

@ -6,6 +6,7 @@
#include <iomanip>
#include <algorithm>
Color3::Color3() {};
Color3::Color3(float r, float g, float b) : r(std::clamp(r, 0.f, 1.f)), g(std::clamp(g, 0.f, 1.f)), b(std::clamp(b, 0.f, 1.f)) {};
Color3::Color3(const glm::vec3& vec) : r(std::clamp(vec.x, 0.f, 1.f)), g(std::clamp(vec.y, 0.f, 1.f)), b(std::clamp(vec.z, 0.f, 1.f)) {};

View file

@ -14,6 +14,7 @@ class DEF_DATA Color3 {
public:
DEF_DATA_CTOR Color3(float r, float g, float b);
Color3();
Color3(const glm::vec3&);
virtual ~Color3();

View file

@ -27,11 +27,11 @@ static CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0,
static rp3d::PhysicsCommon common;
static rp3d::PhysicsWorld* world = common.createPhysicsWorld();
std::shared_ptr<Part> getHandleAdornee() {
std::shared_ptr<BasePart> getHandleAdornee() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) {
if (!inst.expired() && inst.lock()->IsA<Part>())
return inst.lock()->CastTo<Part>().expect();
if (!inst.expired() && inst.lock()->IsA<BasePart>())
return inst.lock()->CastTo<BasePart>().expect();
}
return {};
@ -82,8 +82,8 @@ static int getAABBOfSelection(glm::vec3& pos, glm::vec3& size, glm::vec3& min, g
int count = 0;
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) {
if (inst.expired() || !inst.lock()->IsA<Part>()) continue;
std::shared_ptr<Part> part = inst.lock()->CastTo<Part>().expect();
if (inst.expired() || !inst.lock()->IsA<BasePart>()) continue;
std::shared_ptr<BasePart> part = inst.lock()->CastTo<BasePart>().expect();
if (count == 0)
min = part->position(), max = part->position();
@ -99,12 +99,12 @@ static int getAABBOfSelection(glm::vec3& pos, glm::vec3& size, glm::vec3& min, g
return count;
}
static std::shared_ptr<Part> getFirstSelectedPart() {
static std::shared_ptr<BasePart> getFirstSelectedPart() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (std::weak_ptr<Instance> inst : selection->Get()) {
if (inst.expired() || !inst.lock()->IsA<Part>()) continue;
if (inst.expired() || !inst.lock()->IsA<BasePart>()) continue;
return inst.lock()->CastTo<Part>().expect();
return inst.lock()->CastTo<BasePart>().expect();
}
return {};

View file

@ -1,7 +1,7 @@
#pragma once
#include "datatypes/cframe.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include <array>
#include <memory>
@ -36,7 +36,7 @@ struct Handles {
bool worldMode = false;
};
std::shared_ptr<Part> getHandleAdornee();
std::shared_ptr<BasePart> getHandleAdornee();
CFrame getHandleCFrame(HandleFace face);
CFrame partCFrameFromHandlePos(HandleFace face, Vector3 newPos);
Vector3 handleSize(HandleFace face);

View file

@ -4,7 +4,7 @@
#include "datatypes/ref.h"
#include "objects/datamodel.h"
#include "objects/service/jointsservice.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/workspace.h"
#include <memory>
#include <reactphysics3d/constraint/FixedJoint.h>
@ -54,6 +54,6 @@ void JointInstance::onUpdated(std::string property) {
oldPart1 = part1;
}
std::optional<std::shared_ptr<Workspace>> JointInstance::workspaceOfPart(std::shared_ptr<Part> part) {
std::optional<std::shared_ptr<Workspace>> JointInstance::workspaceOfPart(std::shared_ptr<BasePart> part) {
return part->workspace();
}

View file

@ -8,31 +8,31 @@
//this is necessary ebcause we use std::weak_ptr<Part> without including it in this file
#ifdef __AUTOGEN_EXTRA_INCLUDES__
#include "../part.h"
#include "objects/part/part.h"
#endif
class Part;
class BasePart;
class Workspace;
class DEF_INST_ABSTRACT JointInstance : public Instance {
AUTOGEN_PREAMBLE
std::weak_ptr<Part> oldPart0;
std::weak_ptr<Part> oldPart1;
std::weak_ptr<BasePart> oldPart0;
std::weak_ptr<BasePart> oldPart1;
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;
std::optional<std::shared_ptr<Workspace>> workspaceOfPart(std::shared_ptr<Part>);
std::optional<std::shared_ptr<Workspace>> workspaceOfPart(std::shared_ptr<BasePart>);
void onUpdated(std::string property);
virtual void buildJoint() = 0;
virtual void breakJoint() = 0;
public:
DEF_PROP_(on_update=onUpdated) std::weak_ptr<Part> part0;
DEF_PROP_(on_update=onUpdated) std::weak_ptr<Part> part1;
DEF_PROP_(on_update=onUpdated) std::weak_ptr<BasePart> part0;
DEF_PROP_(on_update=onUpdated) std::weak_ptr<BasePart> part1;
DEF_PROP_(on_update=onUpdated) CFrame c0;
DEF_PROP_(on_update=onUpdated) CFrame c1;

View file

@ -1,6 +1,6 @@
#include "rotate.h"
#include "objects/service/jointsservice.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/workspace.h"
#include "rendering/renderer.h"
#include <reactphysics3d/constraint/HingeJoint.h>

View file

@ -1,6 +1,6 @@
#include "rotatev.h"
#include "objects/service/jointsservice.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/workspace.h"
#include "rendering/renderer.h"
#include <reactphysics3d/constraint/HingeJoint.h>

View file

@ -4,7 +4,7 @@
#include "objects/datamodel.h"
#include "objects/joint/jointinstance.h"
#include "objects/service/jointsservice.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/workspace.h"
#include <memory>
#include <reactphysics3d/constraint/FixedJoint.h>

View file

@ -4,7 +4,7 @@
#include "objects/datamodel.h"
#include "objects/joint/jointinstance.h"
#include "objects/service/jointsservice.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/workspace.h"
#include <memory>
#include <reactphysics3d/constraint/FixedJoint.h>

View file

@ -8,7 +8,7 @@
#include "objects/message.h"
#include "objects/service/jointsservice.h"
#include "objects/model.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/joint/snap.h"
#include "objects/script.h"
#include "objects/service/script/scriptcontext.h"
@ -21,6 +21,7 @@ std::map<std::string, const InstanceType*> INSTANCE_MAP = {
{ "Instance", &Instance::TYPE },
{ "DataModel", &DataModel::TYPE },
{ "BasePart", &BasePart::TYPE },
{ "Part", &Part::TYPE },
{ "Snap", &Snap::TYPE },
{ "Weld", &Weld::TYPE },

View file

@ -1,5 +1,5 @@
#include "part.h"
#include "base/instance.h"
#include "basepart.h"
#include "objects/base/instance.h"
#include "common.h"
#include "datatypes/base.h"
#include "datatypes/cframe.h"
@ -19,15 +19,14 @@
#include <memory>
#include <optional>
Part::Part(): Part(PartConstructParams { .size = glm::vec3(2, 1.2, 4), .color = Color3(0.639216f, 0.635294f, 0.647059f) }) {
BasePart::BasePart(const InstanceType* type): BasePart(type, PartConstructParams { .size = glm::vec3(2, 1.2, 4), .color = Color3(0.639216f, 0.635294f, 0.647059f) }) {
}
Part::Part(PartConstructParams params): PVInstance(&TYPE), cframe(CFrame::FromEulerAnglesXYZ((Vector3)params.rotation) + params.position),
size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
BasePart::BasePart(const InstanceType* type, PartConstructParams params): PVInstance(type), cframe(CFrame::FromEulerAnglesXYZ((Vector3)params.rotation) + params.position),
size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
}
Part::~Part() {
BasePart::~BasePart() {
// This relies on physicsCommon still existing. Be very careful.
if (this->rigidBody && workspace()) {
workspace().value()->DestroyRigidBody(rigidBody);
@ -36,12 +35,12 @@ Part::~Part() {
}
void Part::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) {
void BasePart::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) {
if (this->rigidBody)
this->rigidBody->setIsActive(workspace().has_value());
if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(this->shared_from_this()));
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<BasePart>(this->shared_from_this()));
// Destroy joints
if (!workspace()) BreakJoints();
@ -49,22 +48,22 @@ void Part::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std
// TODO: Sleeping bodies that touch this one also need to be updated
}
void Part::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
newWorkspace->AddBody(shared<Part>());
void BasePart::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
newWorkspace->AddBody(shared<BasePart>());
}
void Part::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
void BasePart::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
if (simulationTicket.has_value())
oldWorkspace->RemoveBody(shared<Part>());
oldWorkspace->RemoveBody(shared<BasePart>());
}
void Part::onUpdated(std::string property) {
void BasePart::onUpdated(std::string property) {
// Reset velocity
if (property != "Velocity")
velocity = Vector3::ZERO;
if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(this->shared_from_this()));
workspace().value()->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 (property != "Anchored")
@ -88,7 +87,7 @@ static Vector3 verts[8] {
{1, 1, 1},
};
Vector3 Part::GetAABB() {
Vector3 BasePart::GetAABB() {
Vector3 min(0, 0, 0);
Vector3 max(0, 0, 0);
for (Vector3 vert : verts) {
@ -99,7 +98,7 @@ Vector3 Part::GetAABB() {
return (min - max).Abs() / 2;
}
void Part::BreakJoints() {
void BasePart::BreakJoints() {
for (std::weak_ptr<JointInstance> joint : primaryJoints) {
if (joint.expired()) continue;
joint.lock()->Destroy();
@ -120,7 +119,7 @@ static Vector3 FACES[6] = {
{0, 0, -1},
};
SurfaceType Part::surfaceFromFace(NormalId face) {
SurfaceType BasePart::surfaceFromFace(NormalId face) {
switch (face) {
case Top: return topSurface;
case Bottom: return bottomSurface;
@ -132,7 +131,7 @@ SurfaceType Part::surfaceFromFace(NormalId face) {
return SurfaceType::Smooth; // Unreachable
}
float Part::GetSurfaceParamA(Vector3 face) {
float BasePart::GetSurfaceParamA(Vector3 face) {
switch (faceFromNormal(face)) {
case Top: return topParamA;
case Bottom: return bottomParamA;
@ -144,7 +143,7 @@ float Part::GetSurfaceParamA(Vector3 face) {
return 0; // Unreachable
}
float Part::GetSurfaceParamB(Vector3 face) {
float BasePart::GetSurfaceParamB(Vector3 face) {
switch (faceFromNormal(face)) {
case Top: return topParamB;
case Bottom: return bottomParamB;
@ -156,14 +155,14 @@ float Part::GetSurfaceParamB(Vector3 face) {
return 0; // Unreachable
}
bool Part::checkJointContinuity(std::shared_ptr<Part> otherPart) {
bool BasePart::checkJointContinuity(std::shared_ptr<BasePart> otherPart) {
// Make sure that the two parts don't depend on one another
return checkJointContinuityUp(otherPart) && checkJointContinuityDown(otherPart);
}
bool Part::checkJointContinuityDown(std::shared_ptr<Part> otherPart) {
if (shared<Part>() == otherPart) return false;
bool BasePart::checkJointContinuityDown(std::shared_ptr<BasePart> otherPart) {
if (shared<BasePart>() == otherPart) return false;
for (auto joint : primaryJoints) {
if (joint.expired() || joint.lock()->part1.expired()) continue;
if (!joint.lock()->part1.lock()->checkJointContinuityDown(otherPart))
@ -172,8 +171,8 @@ bool Part::checkJointContinuityDown(std::shared_ptr<Part> otherPart) {
return true;
}
bool Part::checkJointContinuityUp(std::shared_ptr<Part> otherPart) {
if (shared<Part>() == otherPart) return false;
bool BasePart::checkJointContinuityUp(std::shared_ptr<BasePart> otherPart) {
if (shared<BasePart>() == otherPart) return false;
for (auto joint : secondaryJoints) {
if (joint.expired() || joint.lock()->part0.expired()) continue;
if (!joint.lock()->part0.lock()->checkJointContinuityUp(otherPart))
@ -182,7 +181,7 @@ bool Part::checkJointContinuityUp(std::shared_ptr<Part> otherPart) {
return true;
}
bool Part::checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3 myFace, Vector3 otherFace, std::shared_ptr<Part> otherPart) {
bool BasePart::checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3 myFace, Vector3 otherFace, std::shared_ptr<BasePart> otherPart) {
Vector3 farCorner0 = surfaceFrame.Inverse() * otherPart->cframe * (Vector3::ONE * (otherPart->size / 2.f));
Vector3 farCorner1 = surfaceFrame.Inverse() * otherPart->cframe * (-Vector3::ONE * (otherPart->size / 2.f));
@ -218,7 +217,7 @@ std::optional<std::shared_ptr<JointInstance>> makeJointFromSurfaces(SurfaceType
return std::nullopt;
}
void Part::MakeJoints() {
void BasePart::MakeJoints() {
// Algorithm: Find nearby parts
// Make sure parts are not dependant on each other (via primary/secondaryJoints)
// Find matching surfaces (surface normal dot product < -0.999)
@ -233,8 +232,8 @@ void Part::MakeJoints() {
for (auto it = workspace().value()->GetDescendantsStart(); it != workspace().value()->GetDescendantsEnd(); it++) {
std::shared_ptr<Instance> obj = *it;
if (obj == shared_from_this()) continue; // Skip ourselves
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
std::shared_ptr<Part> otherPart = obj->CastTo<Part>().expect();
if (!obj->IsA<BasePart>()) continue;
std::shared_ptr<BasePart> otherPart = obj->CastTo<BasePart>().expect();
for (Vector3 myFace : FACES) {
Vector3 myWorldNormal = cframe.Rotation() * myFace;
@ -278,8 +277,8 @@ void Part::MakeJoints() {
auto joint_ = makeJointFromSurfaces(mySurface, otherSurface);
if (!joint_) continue;
std::shared_ptr<JointInstance> joint = joint_.value();
joint->part0 = shared<Part>();
joint->part1 = otherPart->shared<Part>();
joint->part0 = shared<BasePart>();
joint->part1 = otherPart->shared<BasePart>();
joint->c0 = contact0;
joint->c1 = contact1;
dataModel().value()->GetService<JointsService>()->AddChild(joint);
@ -291,7 +290,7 @@ void Part::MakeJoints() {
}
}
void Part::trackJoint(std::shared_ptr<JointInstance> joint) {
void BasePart::trackJoint(std::shared_ptr<JointInstance> joint) {
if (!joint->part0.expired() && joint->part0.lock() == shared_from_this()) {
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
// Clean expired refs
@ -325,7 +324,7 @@ void Part::trackJoint(std::shared_ptr<JointInstance> joint) {
}
}
void Part::untrackJoint(std::shared_ptr<JointInstance> joint) {
void BasePart::untrackJoint(std::shared_ptr<JointInstance> joint) {
for (auto it = primaryJoints.begin(); it != primaryJoints.end();) {
// Clean expired refs
if (it->expired() || it->lock() == joint) {

View file

@ -14,7 +14,7 @@
#include <optional>
#include <reactphysics3d/reactphysics3d.h>
#include <vector>
#include "annotation.h"
#include "objects/annotation.h"
#include "objects/pvinstance.h"
namespace rp = reactphysics3d;
@ -34,11 +34,11 @@ class Workspace;
#ifndef __SIMULATION_TICKET
#define __SIMULATION_TICKET
class Part;
typedef std::list<std::shared_ptr<Part>>::iterator SimulationTicket;
class BasePart;
typedef std::list<std::shared_ptr<BasePart>>::iterator SimulationTicket;
#endif
class DEF_INST_(explorer_icon="part") Part : public PVInstance {
class DEF_INST_ABSTRACT_(explorer_icon="part") BasePart : public PVInstance {
AUTOGEN_PREAMBLE
protected:
// Joints where this part is Part0
@ -50,10 +50,10 @@ protected:
void untrackJoint(std::shared_ptr<JointInstance>);
SurfaceType surfaceFromFace(NormalId);
bool checkJointContinuity(std::shared_ptr<Part>);
bool checkJointContinuityUp(std::shared_ptr<Part>);
bool checkJointContinuityDown(std::shared_ptr<Part>);
bool checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3 myFace, Vector3 otherFace, std::shared_ptr<Part> otherPart);
bool checkJointContinuity(std::shared_ptr<BasePart>);
bool checkJointContinuityUp(std::shared_ptr<BasePart>);
bool checkJointContinuityDown(std::shared_ptr<BasePart>);
bool checkSurfacesTouching(CFrame surfaceFrame, Vector3 size, Vector3 myFace, Vector3 otherFace, std::shared_ptr<BasePart> otherPart);
friend JointInstance;
friend Workspace;
@ -62,6 +62,9 @@ protected:
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 onUpdated(std::string);
BasePart(const InstanceType*);
BasePart(const InstanceType*, PartConstructParams params);
public:
DEF_PROP_CATEGORY(DATA)
DEF_PROP_(on_update=onUpdated) Vector3 velocity;
@ -116,13 +119,7 @@ public:
float GetSurfaceParamA(Vector3 face);
float GetSurfaceParamB(Vector3 face);
Part();
Part(PartConstructParams params);
~Part() override;
static inline std::shared_ptr<Part> New() { return std::make_shared<Part>(); };
static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); };
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Part>(); };
~BasePart() override;
inline Vector3 position() { return cframe.Position(); }

View file

@ -0,0 +1,8 @@
#include "part.h"
Part::Part(): BasePart(&TYPE) {
}
Part::Part(PartConstructParams params): BasePart(&TYPE, params) {
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "basepart.h"
#include "objects/annotation.h"
class DEF_INST Part : public BasePart {
AUTOGEN_PREAMBLE
public:
Part();
Part(PartConstructParams params);
static inline std::shared_ptr<Part> New() { return std::make_shared<Part>(); };
static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); };
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Part>(); };
};

View file

@ -4,7 +4,7 @@
#include "datatypes/vector.h"
#include "logger.h"
#include "objects/base/instance.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/jointsservice.h"
#include "objects/joint/jointinstance.h"
#include "objects/datamodel.h"
@ -39,8 +39,8 @@ void PhysicsEventListener::onContact(const rp::CollisionCallback::CallbackData&
continue;
ContactItem contact;
contact.part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
contact.part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
contact.part0 = reinterpret_cast<BasePart*>(pair.getBody1()->getUserData())->shared<BasePart>();
contact.part1 = reinterpret_cast<BasePart*>(pair.getBody2()->getUserData())->shared<BasePart>();
contact.action = type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart ? ContactItem::CONTACTITEM_TOUCHED : ContactItem::CONTACTITEM_TOUCHENDED;
workspace->contactQueue.push(contact);
@ -55,8 +55,8 @@ void PhysicsEventListener::onTrigger(const rp::OverlapCallback::CallbackData& da
auto type = pair.getEventType();
if (type == rp::OverlapCallback::OverlapPair::EventType::OverlapStay) continue;
auto part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
auto part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
auto part0 = reinterpret_cast<BasePart*>(pair.getBody1()->getUserData())->shared<BasePart>();
auto part1 = reinterpret_cast<BasePart*>(pair.getBody2()->getUserData())->shared<BasePart>();
if (type == reactphysics3d::OverlapCallback::OverlapPair::EventType::OverlapStart) {
part0->Touched->Fire({ (Variant)InstanceRef(part1) });
@ -85,8 +85,8 @@ void Workspace::InitService() {
// Sync all parts
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
std::shared_ptr<Instance> obj = *it;
if (!obj->IsA<Part>()) continue;
std::shared_ptr<Part> part = obj->CastTo<Part>().expect();
if (!obj->IsA<BasePart>()) continue;
std::shared_ptr<BasePart> part = obj->CastTo<BasePart>().expect();
part->MakeJoints();
}
@ -105,7 +105,7 @@ void Workspace::InitService() {
}
}
void Workspace::updatePartPhysics(std::shared_ptr<Part> part) {
void Workspace::updatePartPhysics(std::shared_ptr<BasePart> part) {
rp::Transform transform = part->cframe;
if (!part->rigidBody) {
part->rigidBody = physicsWorld->createRigidBody(transform);
@ -162,7 +162,7 @@ void Workspace::ProcessContactEvents() {
contactQueueLock.unlock();
}
void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
void Workspace::SyncPartPhysics(std::shared_ptr<BasePart> part) {
if (globalPhysicsLock.try_lock()) {
updatePartPhysics(part);
globalPhysicsLock.unlock();
@ -192,7 +192,7 @@ void Workspace::PhysicsStep(float deltaTime) {
queueLock.unlock();
// TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance
for (std::shared_ptr<Part> part : simulatedBodies) {
for (std::shared_ptr<BasePart> part : simulatedBodies) {
// If the part's body is dirty, update it now instead
if (part->rigidBodyDirty) {
updatePartPhysics(part);
@ -261,7 +261,7 @@ class NearestRayHit : public rp::RaycastCallback {
return 1;
}
std::shared_ptr<Part> part = partFromBody(raycastInfo.body);
std::shared_ptr<BasePart> part = partFromBody(raycastInfo.body);
FilterResult result = filter.value()(part);
if (result == FilterResult::BLOCK) {
nearestHit = std::nullopt;
@ -305,14 +305,14 @@ rp::Joint* Workspace::CreateJoint(const rp::JointInfo& jointInfo) {
return joint;
}
void Workspace::AddBody(std::shared_ptr<Part> part) {
void Workspace::AddBody(std::shared_ptr<BasePart> part) {
queueLock.lock();
bodyQueue.push_back({part, QueueItem::QUEUEITEM_ADD});
part->rigidBodyDirty = true;
queueLock.unlock();
}
void Workspace::RemoveBody(std::shared_ptr<Part> part) {
void Workspace::RemoveBody(std::shared_ptr<BasePart> part) {
queueLock.lock();
bodyQueue.push_back({part, QueueItem::QUEUEITEM_REMOVE});
queueLock.unlock();

View file

@ -32,7 +32,7 @@ enum FilterResult {
PASS, // The object is transparent, ignore it
};
class Part;
class BasePart;
class Snap;
class Weld;
class Rotate;
@ -40,13 +40,13 @@ class RotateV;
#ifndef __SIMULATION_TICKET
#define __SIMULATION_TICKET
typedef std::list<std::shared_ptr<Part>>::iterator SimulationTicket;
typedef std::list<std::shared_ptr<BasePart>>::iterator SimulationTicket;
#endif
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
typedef std::function<FilterResult(std::shared_ptr<BasePart>)> RaycastFilter;
struct QueueItem {
std::shared_ptr<Part> part;
std::shared_ptr<BasePart> part;
enum {
QUEUEITEM_ADD,
QUEUEITEM_REMOVE,
@ -54,8 +54,8 @@ struct QueueItem {
};
struct ContactItem {
std::shared_ptr<Part> part0;
std::shared_ptr<Part> part1;
std::shared_ptr<BasePart> part0;
std::shared_ptr<BasePart> part1;
enum {
CONTACTITEM_TOUCHED,
CONTACTITEM_TOUCHENDED,
@ -78,7 +78,7 @@ class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
friend PhysicsEventListener;
std::list<std::shared_ptr<Part>> simulatedBodies;
std::list<std::shared_ptr<BasePart>> simulatedBodies;
std::list<QueueItem> bodyQueue;
std::queue<ContactItem> contactQueue;
std::mutex contactQueueLock;
@ -86,7 +86,7 @@ class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
static rp::PhysicsCommon* physicsCommon;
PhysicsEventListener physicsEventListener;
void updatePartPhysics(std::shared_ptr<Part> part);
void updatePartPhysics(std::shared_ptr<BasePart> part);
protected:
void InitService() override;
bool initialized = false;
@ -103,10 +103,10 @@ public:
// static inline std::shared_ptr<Workspace> New() { return std::make_shared<Workspace>(); };
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Workspace>(); };
void AddBody(std::shared_ptr<Part> part);
void RemoveBody(std::shared_ptr<Part> part);
void AddBody(std::shared_ptr<BasePart> part);
void RemoveBody(std::shared_ptr<BasePart> part);
void DestroyRigidBody(rp::RigidBody* rigidBody);
void SyncPartPhysics(std::shared_ptr<Part> part);
void SyncPartPhysics(std::shared_ptr<BasePart> part);
rp::Joint* CreateJoint(const rp::JointInfo& jointInfo);
void DestroyJoint(rp::Joint* joint);

View file

@ -5,13 +5,13 @@
#include "datatypes/vector.h"
#include "math_helper.h"
#include "objects/base/instance.h"
#include "objects/part.h"
#include "objects/part/part.h"
#include "objects/service/selection.h"
#include <glm/common.hpp>
#include <memory>
#include <vector>
PartAssembly::PartAssembly(std::vector<std::shared_ptr<Part>> parts, bool worldMode) : parts(parts) {
PartAssembly::PartAssembly(std::vector<std::shared_ptr<BasePart>> parts, bool worldMode) : parts(parts) {
if (parts.size() == 0) return;
if (parts.size() == 1 && !worldMode) {
_assemblyOrigin = parts[0]->cframe;
@ -36,19 +36,19 @@ PartAssembly::PartAssembly(std::vector<std::shared_ptr<Part>> parts, bool worldM
}
PartAssembly PartAssembly::FromSelection(std::vector<std::shared_ptr<Instance>> newSelection) {
std::vector<std::shared_ptr<Part>> selection;
std::vector<std::shared_ptr<BasePart>> selection;
for (std::shared_ptr<Instance> obj : newSelection) {
if (!obj->IsA<PVInstance>()) continue;
if (obj->IsA<Part>())
selection.push_back(obj->CastTo<Part>().expect());
if (obj->IsA<BasePart>())
selection.push_back(obj->CastTo<BasePart>().expect());
// Add object descendants
for (DescendantsIterator it = obj->GetDescendantsStart(); it != obj->GetDescendantsEnd(); it++) {
if (!(*it)->IsA<Part>()) continue;
if (!(*it)->IsA<BasePart>()) continue;
selection.push_back((*it)->CastTo<Part>().expect());
selection.push_back((*it)->CastTo<BasePart>().expect());
}
}

View file

@ -4,12 +4,12 @@
#include <memory>
#include <vector>
class Part;
class BasePart;
class Instance;
class Selection;
struct PartTransformState {
std::shared_ptr<Part> part;
std::shared_ptr<BasePart> part;
Vector3 size;
CFrame cframe;
};
@ -19,9 +19,9 @@ class PartAssembly {
Vector3 _bounds;
Vector3 _size;
std::vector<std::shared_ptr<Part>> parts;
std::vector<std::shared_ptr<BasePart>> parts;
public:
PartAssembly(std::vector<std::shared_ptr<Part>>, bool worldMode = false);
PartAssembly(std::vector<std::shared_ptr<BasePart>>, bool worldMode = false);
static PartAssembly FromSelection(std::vector<std::shared_ptr<Instance>> selection);
static PartAssembly FromSelection(std::shared_ptr<Selection> selection);

View file

@ -7,7 +7,7 @@
#include <reactphysics3d/mathematics/Vector3.h>
#include <reactphysics3d/mathematics/mathematics.h>
#include <glm/ext.hpp>
#include "objects/part.h"
#include "objects/part/part.h"
namespace rp = reactphysics3d;
@ -32,8 +32,8 @@ inline glm::quat rpToGlm(rp::Quaternion quat) {
}
// Make this std::optional
inline std::shared_ptr<Part> partFromBody(rp::Body* body) {
Part* raw = reinterpret_cast<Part*>(body->getUserData());
std::shared_ptr<Part> shared = std::dynamic_pointer_cast<Part>(raw->shared_from_this());
inline std::shared_ptr<BasePart> partFromBody(rp::Body* body) {
BasePart* raw = reinterpret_cast<BasePart*>(body->getUserData());
std::shared_ptr<BasePart> shared = std::dynamic_pointer_cast<BasePart>(raw->shared_from_this());
return shared;
}

View file

@ -43,6 +43,36 @@ static float CUBE_VERTICES[] = {
};
static float WEDGE_VERTICES[] = {
// positions // normals // texture coords
0.5, 0.5, 0.5, -0.0, -0.0, 1.0, 0.625, 0.75,
-0.5, -0.5, 0.5, -0.0, -0.0, 1.0, 0.375, 1.0,
0.5, -0.5, 0.5, -0.0, -0.0, 1.0, 0.375, 0.75,
-0.5, -0.5, 0.5, -1.0, -0.0, -0.0, 0.375, 0.0,
-0.5, 0.5, 0.5, -1.0, -0.0, -0.0, 0.625, 0.0,
-0.5, -0.5, -0.5, -1.0, -0.0, -0.0, 0.375, 0.25,
0.5, -0.5, -0.5, -0.0, -1.0, -0.0, 0.375, 0.5,
-0.5, -0.5, 0.5, -0.0, -1.0, -0.0, 0.125, 0.75,
-0.5, -0.5, -0.5, -0.0, -1.0, -0.0, 0.125, 0.5,
0.5, -0.5, -0.5, 1.0, -0.0, -0.0, 0.375, 0.5,
0.5, 0.5, 0.5, 1.0, -0.0, -0.0, 0.625, 0.75,
0.5, -0.5, 0.5, 1.0, -0.0, -0.0, 0.375, 0.75,
-0.5, 0.5, 0.5, -0.0, 0.7071, -0.7071, 0.875, 0.75,
0.5, -0.5, -0.5, -0.0, 0.7071, -0.7071, 0.375, 0.5,
-0.5, -0.5, -0.5, -0.0, 0.7071, -0.7071, 0.375, 0.25,
0.5, 0.5, 0.5, -0.0, -0.0, 1.0, 0.625, 0.75,
-0.5, 0.5, 0.5, -0.0, -0.0, 1.0, 0.625, 1.0,
-0.5, -0.5, 0.5, -0.0, -0.0, 1.0, 0.375, 1.0,
0.5, -0.5, -0.5, -0.0, -1.0, -0.0, 0.375, 0.5,
0.5, -0.5, 0.5, -0.0, -1.0, -0.0, 0.375, 0.75,
-0.5, -0.5, 0.5, -0.0, -1.0, -0.0, 0.125, 0.75,
-0.5, 0.5, 0.5, -0.0, 0.7071, -0.7071, 0.875, 0.75,
0.5, 0.5, 0.5, -0.0, 0.7071, -0.7071, 0.625, 0.75,
0.5, -0.5, -0.5, -0.0, 0.7071, -0.7071, 0.375, 0.5,
};
static float SPHERE_VERTICES[] = {
// positions // normals // texture coords
@ -1730,6 +1760,7 @@ static float CYLINDER_VERTICES[] = {
};
Mesh* CUBE_MESH;
Mesh* WEDGE_MESH;
Mesh* SPHERE_MESH;
Mesh* ARROW_MESH;
Mesh* OUTLINE_MESH;
@ -1737,6 +1768,7 @@ Mesh* CYLINDER_MESH;
void initMeshes() {
CUBE_MESH = new Mesh(sizeof(CUBE_VERTICES) / sizeof(float) / 8, CUBE_VERTICES);
WEDGE_MESH = new Mesh(sizeof(WEDGE_VERTICES) / sizeof(float) / 8, WEDGE_VERTICES);
SPHERE_MESH = new Mesh(sizeof(SPHERE_VERTICES) / sizeof(float) / 8, SPHERE_VERTICES);
ARROW_MESH = new Mesh(sizeof(ARROW_VERTICES) / sizeof(float) / 8, ARROW_VERTICES);
OUTLINE_MESH = new Mesh(sizeof(OUTLINE_VERTICES) / sizeof(float) / 8, OUTLINE_VERTICES);

View file

@ -31,9 +31,9 @@
#include "shader.h"
#include "mesh.h"
#include "defaultmeshes.h"
#include "../camera.h"
#include "../common.h"
#include "../objects/part.h"
#include "camera.h"
#include "common.h"
#include "objects/part/part.h"
#include "skybox.h"
#include "enum/surface.h"
#include "texture3d.h"
@ -170,11 +170,11 @@ void renderParts() {
shader->set("viewPos", camera.cameraPos);
// Sort by nearest
std::map<float, std::shared_ptr<Part>> sorted;
std::map<float, std::shared_ptr<BasePart>> sorted;
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
std::shared_ptr<Instance> inst = *it;
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
if (part->transparency > 0.00001) {
float distance = glm::length(glm::vec3(Vector3(camera.cameraPos) - part->position()));
sorted[distance] = part;
@ -207,8 +207,8 @@ void renderParts() {
// TODO: Same as todo in src/physics/simulation.cpp
// According to LearnOpenGL, std::map automatically sorts its contents.
for (std::map<float, std::shared_ptr<Part>>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); it++) {
std::shared_ptr<Part> part = it->second;
for (std::map<float, std::shared_ptr<BasePart>>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); it++) {
std::shared_ptr<BasePart> part = it->second;
glm::mat4 model = part->cframe;
// if (part->name == "camera") model = camera.getLookAt();
model = glm::scale(model, (glm::vec3)part->size);
@ -268,7 +268,7 @@ void renderSurfaceExtras() {
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
std::shared_ptr<Instance> inst = *it;
if (!inst->IsA("Part")) continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
for (int i = 0; i < 6; i++) {
NormalId face = (NormalId)i;
SurfaceType type = part->GetSurfaceFromFace(face);
@ -396,7 +396,7 @@ void renderAABB() {
// Sort by nearest
for (std::shared_ptr<Instance> inst : gWorkspace()->GetChildren()) {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
glm::mat4 model = CFrame::IDENTITY + part->cframe.Position();
printf("AABB is supposedly (%f, %f, %f)\n", part->GetAABB().X(), part->GetAABB().Y(), part->GetAABB().Z());
model = glm::scale(model, (glm::vec3)part->GetAABB());
@ -436,7 +436,7 @@ void renderWireframe() {
// Sort by nearest
for (std::shared_ptr<Instance> inst : gWorkspace()->GetChildren()) {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
glm::mat4 model = part->cframe;
model = glm::scale(model, (glm::vec3)part->size);
wireframeShader->set("model", model);
@ -478,8 +478,8 @@ void renderOutlines() {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
for (auto inst : selection->Get()) {
if (inst->GetClass() != &Part::TYPE) continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
if (inst->GetClass() != &BasePart::TYPE) continue;
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(inst);
if (first)
min = part->position(), max = part->position();

View file

@ -105,7 +105,7 @@ However, Autogen cannot tell where this class came from to automatically include
block via `__AUTOGEN_EXTRA_INCLUDES__`:
#ifdef __AUTOGEN_EXTRA_INCLUDES__
#include "objects/part.h"
#include "objects/part/part.h"
#endif
class Part;

View file

@ -59,7 +59,7 @@ void MainGLWidget::resizeGL(int w, int h) {
glm::vec2 firstPoint;
glm::vec2 secondPoint;
extern std::weak_ptr<Part> draggingObject;
extern std::weak_ptr<BasePart> draggingObject;
extern std::optional<HandleFace> draggingHandle;
extern Shader* shader;
void MainGLWidget::paintGL() {
@ -125,7 +125,7 @@ std::vector<PartTransformState> initialTransforms;
bool tryMouseContextMenu = false;
bool isMouseDragging = false;
std::weak_ptr<Part> draggingObject;
std::weak_ptr<BasePart> draggingObject;
std::optional<HandleFace> draggingHandle;
Vector3 initialHitPos;
Vector3 initialHitNormal;
@ -396,7 +396,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
if (!rayHit || !partFromBody(rayHit->body)) { selection->Set({}); return; }
std::shared_ptr<Part> part = partFromBody(rayHit->body);
std::shared_ptr<BasePart> part = partFromBody(rayHit->body);
if (part->locked) { selection->Set({}); return; }
std::shared_ptr<PVInstance> selObject = part;

View file

@ -1,7 +1,7 @@
#ifndef MAINGLWIDGET_H
#define MAINGLWIDGET_H
#include "objects/part.h"
#include "objects/part/part.h"
#include "qevent.h"
#include <QOpenGLWidget>
#include <QWidget>
@ -15,7 +15,7 @@ class MainGLWidget : public QOpenGLWidget {
public:
MainGLWidget(QWidget *parent = nullptr);
void updateCycle();
std::shared_ptr<Part> lastPart;
std::shared_ptr<BasePart> lastPart;
void buildContextMenu();
protected:

View file

@ -130,7 +130,7 @@ void PlaceDocument::closeEvent(QCloseEvent *closeEvent) {
closeEvent->ignore();
}
std::shared_ptr<Part> shit;
std::shared_ptr<BasePart> shit;
void PlaceDocument::timerEvent(QTimerEvent* evt) {
if (evt->timerId() != timer.timerId()) {
QWidget::timerEvent(evt);
@ -148,7 +148,7 @@ void PlaceDocument::init() {
timer.start(33, this);
placeWidget->buildContextMenu();
std::shared_ptr<Part> lastPart;
std::shared_ptr<BasePart> lastPart;
// Baseplate
gWorkspace()->AddChild(lastPart = Part::New({
.position = glm::vec3(0, -5, 0),