misc(datatypes): added alias for vector3, cframe, and color3 via using

This commit is contained in:
maelstrom 2025-04-23 19:33:59 +02:00
parent d4f7582780
commit 6799b93a06
19 changed files with 157 additions and 153 deletions

View file

@ -32,7 +32,7 @@ Data::CFrame::CFrame(glm::vec3 translation, glm::mat3 rotation)
, rotation(rotation) {
}
Data::CFrame::CFrame(Data::Vector3 position, glm::quat quat)
Data::CFrame::CFrame(Vector3 position, glm::quat quat)
: translation(position)
, rotation(quat) {
}
@ -40,17 +40,17 @@ Data::CFrame::CFrame(Data::Vector3 position, glm::quat quat)
Data::CFrame::CFrame(const rp::Transform& transform) : Data::CFrame::CFrame(rpToGlm(transform.getPosition()), rpToGlm(transform.getOrientation())) {
}
glm::mat3 lookAt(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up) {
glm::mat3 lookAt(Vector3 position, Vector3 lookAt, Vector3 up) {
// https://github.com/sgorsten/linalg/issues/29#issuecomment-743989030
Data::Vector3 f = (lookAt - position).Unit(); // Forward/Look
Data::Vector3 u = up.Unit(); // Up
Data::Vector3 s = f.Cross(u).Unit(); // Right
Vector3 f = (lookAt - position).Unit(); // Forward/Look
Vector3 u = up.Unit(); // Up
Vector3 s = f.Cross(u).Unit(); // Right
u = s.Cross(f).Unit();
return { s, u, -f };
}
Data::CFrame::CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up)
Data::CFrame::CFrame(Vector3 position, Vector3 lookAt, Vector3 up)
: translation(position)
, rotation(::lookAt(position, lookAt, up)) {
}
@ -61,7 +61,7 @@ const Data::TypeInfo Data::CFrame::TYPE = {
.deserializer = &Data::CFrame::Deserialize,
};
const Data::TypeInfo& Data::CFrame::GetType() const { return Data::Vector3::TYPE; };
const Data::TypeInfo& Data::CFrame::GetType() const { return Vector3::TYPE; };
const Data::String Data::CFrame::ToString() const {
return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z());
@ -76,17 +76,17 @@ Data::CFrame::operator rp::Transform() const {
return rp::Transform(glmToRp(translation), glmToRp(rotation));
}
Data::Vector3 Data::CFrame::ToEulerAnglesXYZ() {
Vector3 Data::CFrame::ToEulerAnglesXYZ() {
float x;
float y;
float z;
glm::extractEulerAngleXYZ(glm::mat4(this->rotation), x, y, z);
return Data::Vector3(x, y, z);
return Vector3(x, y, z);
}
Data::CFrame Data::CFrame::FromEulerAnglesXYZ(Data::Vector3 vector) {
Data::CFrame Data::CFrame::FromEulerAnglesXYZ(Vector3 vector) {
glm::mat3 mat = glm::eulerAngleXYZ(vector.X(), vector.Y(), vector.Z());
return Data::CFrame((glm::vec3)Data::Vector3::ZERO, mat);
return Data::CFrame((glm::vec3)Vector3::ZERO, mat);
}
Data::CFrame Data::CFrame::Inverse() const {
@ -100,15 +100,15 @@ Data::CFrame Data::CFrame::operator *(Data::CFrame otherFrame) const {
return CFrame { this->translation + this->rotation * otherFrame.translation, this->rotation * otherFrame.rotation };
}
Data::Vector3 Data::CFrame::operator *(Data::Vector3 vector) const {
Vector3 Data::CFrame::operator *(Vector3 vector) const {
return this->translation + this->rotation * vector;
}
Data::CFrame Data::CFrame::operator +(Data::Vector3 vector) const {
Data::CFrame Data::CFrame::operator +(Vector3 vector) const {
return CFrame { this->translation + glm::vec3(vector), this->rotation };
}
Data::CFrame Data::CFrame::operator -(Data::Vector3 vector) const {
Data::CFrame Data::CFrame::operator -(Vector3 vector) const {
return *this + -vector;
}

View file

@ -23,8 +23,8 @@ namespace Data {
CFrame();
CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22);
CFrame(const rp::Transform&);
CFrame(Data::Vector3 position, glm::quat quat);
CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up = Data::Vector3(0, 1, 0));
CFrame(Vector3 position, glm::quat quat);
CFrame(Vector3 position, Vector3 lookAt, Vector3 up = Vector3(0, 1, 0));
~CFrame();
static const CFrame IDENTITY;
@ -53,12 +53,14 @@ namespace Data {
inline Vector3 LookVector() { return -glm::column(rotation, 2); }
Vector3 ToEulerAnglesXYZ();
static CFrame FromEulerAnglesXYZ(Data::Vector3);
static CFrame FromEulerAnglesXYZ(Vector3);
// Operators
Data::CFrame operator *(Data::CFrame) const;
Data::Vector3 operator *(Data::Vector3) const;
Data::CFrame operator +(Data::Vector3) const;
Data::CFrame operator -(Data::Vector3) const;
Vector3 operator *(Vector3) const;
Data::CFrame operator +(Vector3) const;
Data::CFrame operator -(Vector3) const;
};
}
using Data::CFrame;

View file

@ -35,3 +35,5 @@ namespace Data {
inline float B() const { return b; }
};
}
using Data::Color3;

View file

@ -29,6 +29,6 @@ void Data::InstanceRef::Serialize(pugi::xml_node node) const {
// node.text().set(this->ToHex());
}
// Data::Variant Data::Color3::Deserialize(pugi::xml_node node) {
// Data::Variant Color3::Deserialize(pugi::xml_node node) {
// return Color3::FromHex(node.text().get());
// }

View file

@ -55,6 +55,8 @@ namespace Data {
};
}
using Data::Vector3;
inline void printVec(Data::Vector3 vec) {
printf("(%f, %f, %f)\n", vec.X(), vec.Y(), vec.Z());
}

View file

@ -17,7 +17,7 @@ HandleFace HandleFace::ZPos(4, glm::vec3(0,0,1));
HandleFace HandleFace::ZNeg(5, glm::vec3(0,0,-1));
std::array<HandleFace, 6> HandleFace::Faces { HandleFace::XPos, HandleFace::XNeg, HandleFace::YPos, HandleFace::YNeg, HandleFace::ZPos, HandleFace::ZNeg };
static Data::CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0, 1));
static CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0, 1));
// Shitty solution
static rp3d::PhysicsCommon common;
@ -37,12 +37,12 @@ const InstanceType* Handles::GetClass() {
Handles::Handles(): Instance(&TYPE) {
}
Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
CFrame Handles::GetCFrameOfHandle(HandleFace face) {
if (adornee.expired()) return CFrame(glm::vec3(0,0,0), (Vector3)glm::vec3(0,0,0));
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
CFrame localFrame = worldMode ? CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
Data::Vector3 handleNormal = face.normal;
Vector3 handleNormal = face.normal;
if (nixAxes)
handleNormal = XYZToZXY * face.normal;
@ -52,21 +52,21 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
upAxis = glm::vec3(0, 1, 0);
glm::vec3 partSize = handlesType == HandlesType::RotateHandles ? glm::vec3(glm::max(adornee.lock()->size.x, adornee.lock()->size.y, adornee.lock()->size.z)) : adornee.lock()->size;
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + partSize * 0.5f);
Data::Vector3 handlePos = localFrame * (handleOffset * handleNormal);
Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis);
Vector3 handleOffset = this->worldMode ? ((Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Vector3(2.f + partSize * 0.5f);
Vector3 handlePos = localFrame * (handleOffset * handleNormal);
CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis);
return cframe;
}
Data::CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos) {
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Vector3 newPos) {
if (adornee.expired()) return CFrame(glm::vec3(0,0,0), (Vector3)glm::vec3(0,0,0));
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
Data::CFrame inverseFrame = localFrame.Inverse();
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee.lock()->size * 0.5f);
CFrame localFrame = worldMode ? CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
CFrame inverseFrame = localFrame.Inverse();
Vector3 handleOffset = this->worldMode ? ((Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Vector3(2.f + adornee.lock()->size * 0.5f);
Data::Vector3 handlePos = localFrame * (handleOffset * face.normal);
Vector3 handlePos = localFrame * (handleOffset * face.normal);
// glm::vec3 localPos = inverseFrame * newPos;
glm::vec3 newPartPos = newPos - localFrame.Rotation() * (handleOffset * face.normal);
@ -75,11 +75,11 @@ Data::CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Data::Vector3 new
std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
for (HandleFace face : HandleFace::Faces) {
Data::CFrame cframe = GetCFrameOfHandle(face);
CFrame cframe = GetCFrameOfHandle(face);
// Implement manual detection via boxes instead of... this shit
// This code also hardly works, and is not good at all... Hooo nope.
rp3d::RigidBody* body = world->createRigidBody(Data::CFrame::IDENTITY + cframe.Position());
body->addCollider(common.createBoxShape(cframe.Rotation() * Data::Vector3(HandleSize(face) / 2.f)), rp3d::Transform::identity());
rp3d::RigidBody* body = world->createRigidBody(CFrame::IDENTITY + cframe.Position());
body->addCollider(common.createBoxShape(cframe.Rotation() * Vector3(HandleSize(face) / 2.f)), rp3d::Transform::identity());
rp3d::RaycastInfo info;
if (body->raycast(ray, info)) {
@ -93,7 +93,7 @@ std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
return std::nullopt;
}
Data::Vector3 Handles::HandleSize(HandleFace face) {
Vector3 Handles::HandleSize(HandleFace face) {
if (handlesType == HandlesType::MoveHandles)
return glm::vec3(0.5f, 0.5f, 2.f);
return glm::vec3(1,1,1);

View file

@ -46,9 +46,9 @@ public:
// World-space handles vs local-space handles
bool worldMode = false;
Data::CFrame GetCFrameOfHandle(HandleFace face);
Data::CFrame PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos);
Data::Vector3 HandleSize(HandleFace face);
CFrame GetCFrameOfHandle(HandleFace face);
CFrame PartCFrameFromHandlePos(HandleFace face, Vector3 newPos);
Vector3 HandleSize(HandleFace face);
std::optional<HandleFace> RaycastHandle(rp3d::Ray ray);
static inline std::shared_ptr<Handles> New() { return std::make_shared<Handles>(); };

View file

@ -36,13 +36,13 @@ JointInstance::JointInstance(const InstanceType* type): Instance(type) {
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C0", {
.backingField = &c0,
.type = &Data::CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(),
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C1", {
.backingField = &c1,
.type = &Data::CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(),
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}},
}

View file

@ -25,8 +25,8 @@ public:
std::weak_ptr<Part> part0;
std::weak_ptr<Part> part1;
Data::CFrame c0;
Data::CFrame c1;
CFrame c0;
CFrame c1;
JointInstance(const InstanceType*);
~JointInstance();

View file

@ -38,7 +38,7 @@ void Snap::buildJoint() {
// 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);
CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
part1.lock()->cframe = newFrame;
workspace->SyncPartPhysics(part1.lock());

View file

@ -38,7 +38,7 @@ void Weld::buildJoint() {
// 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);
CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
part1.lock()->cframe = newFrame;
workspace->SyncPartPhysics(part1.lock());

View file

@ -14,8 +14,6 @@
#include <memory>
#include <optional>
using Data::Vector3;
// template <typename T, typename U>
// constexpr FieldCodec fieldCodecOf() {
// return FieldCodec {
@ -31,11 +29,11 @@ using Data::Vector3;
constexpr FieldCodec cframePositionCodec() {
return FieldCodec {
.write = [](Data::Variant source, void* destination) {
Data::CFrame* cframe = static_cast<Data::CFrame*>(destination);
CFrame* cframe = static_cast<CFrame*>(destination);
*cframe = cframe->Rotation() + source.get<Vector3>();
},
.read = [](void* source) -> Data::Variant {
return static_cast<Data::CFrame*>(source)->Position();
return static_cast<CFrame*>(source)->Position();
},
};
}
@ -43,11 +41,11 @@ constexpr FieldCodec cframePositionCodec() {
constexpr FieldCodec cframeRotationCodec() {
return FieldCodec {
.write = [](Data::Variant source, void* destination) {
Data::CFrame* cframe = static_cast<Data::CFrame*>(destination);
*cframe = Data::CFrame::FromEulerAnglesXYZ(source.get<Vector3>()) + cframe->Position();
CFrame* cframe = static_cast<CFrame*>(destination);
*cframe = CFrame::FromEulerAnglesXYZ(source.get<Vector3>()) + cframe->Position();
},
.read = [](void* source) -> Data::Variant {
return static_cast<Data::CFrame*>(source)->ToEulerAnglesXYZ();
return static_cast<CFrame*>(source)->ToEulerAnglesXYZ();
},
};
}
@ -63,10 +61,10 @@ const InstanceType* Part::GetClass() {
return &TYPE;
}
Part::Part(): Part(PartConstructParams { .color = Data::Color3(0.639216f, 0.635294f, 0.647059f) }) {
Part::Part(): Part(PartConstructParams { .color = Color3(0.639216f, 0.635294f, 0.647059f) }) {
}
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame::FromEulerAnglesXYZ((Data::Vector3)params.rotation) + params.position),
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(CFrame::FromEulerAnglesXYZ((Vector3)params.rotation) + params.position),
size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap),
@ -97,12 +95,12 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame::Fr
}}, { "Velocity", {
.backingField = &velocity,
.type = &Vector3::TYPE,
.codec = fieldCodecOf<Data::Vector3>(),
.codec = fieldCodecOf<Vector3>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "CFrame", {
.backingField = &cframe,
.type = &Data::CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(),
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "Size", {
.backingField = &size,
@ -112,8 +110,8 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame::Fr
.category = PROP_CATEGORY_PART,
}}, { "Color", {
.backingField = &color,
.type = &Data::Color3::TYPE,
.codec = fieldCodecOf<Data::Color3>(),
.type = &Color3::TYPE,
.codec = fieldCodecOf<Color3>(),
.category = PROP_CATEGORY_APPEARENCE,
}}, { "Transparency", {
.backingField = &transparency,
@ -191,7 +189,7 @@ void Part::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std
void Part::onUpdated(std::string property) {
// Reset velocity
if (property != "Velocity")
velocity = Data::Vector3::ZERO;
velocity = Vector3::ZERO;
if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(this->shared_from_this()));
@ -221,7 +219,7 @@ Vector3 Part::GetAABB() {
Vector3 min(0, 0, 0);
Vector3 max(0, 0, 0);
for (Vector3 vert : verts) {
Vector3 worldVert = this->cframe.Rotation() * ((Data::Vector3)this->size * vert);
Vector3 worldVert = this->cframe.Rotation() * ((Vector3)this->size * vert);
expandMaxExtents(&min, &max, worldVert);
}
@ -240,7 +238,7 @@ void Part::BreakJoints() {
}
}
static Data::Vector3 FACES[6] = {
static Vector3 FACES[6] = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
@ -314,15 +312,15 @@ void Part::MakeJoints() {
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();
for (Data::Vector3 myFace : FACES) {
Data::Vector3 myWorldNormal = cframe.Rotation() * myFace;
Data::Vector3 validUp = cframe.Rotation() * Data::Vector3(1,1,1).Unit(); // If myFace == (0, 1, 0), then (0, 1, 0) would produce NaN as up, so we fudge the up so that it works
Data::CFrame surfaceFrame(cframe.Position(), cframe * (myFace * size), validUp);
for (Vector3 myFace : FACES) {
Vector3 myWorldNormal = cframe.Rotation() * myFace;
Vector3 validUp = cframe.Rotation() * Vector3(1,1,1).Unit(); // If myFace == (0, 1, 0), then (0, 1, 0) would produce NaN as up, so we fudge the up so that it works
CFrame surfaceFrame(cframe.Position(), cframe * (myFace * size), validUp);
for (Data::Vector3 otherFace : FACES) {
Data::Vector3 otherWorldNormal = otherPart->cframe.Rotation() * otherFace;
Data::Vector3 otherSurfaceCenter = otherPart->cframe * (otherFace * otherPart->size);
Data::Vector3 surfacePointLocalToMyFrame = surfaceFrame.Inverse() * otherSurfaceCenter;
for (Vector3 otherFace : FACES) {
Vector3 otherWorldNormal = otherPart->cframe.Rotation() * otherFace;
Vector3 otherSurfaceCenter = otherPart->cframe * (otherFace * otherPart->size);
Vector3 surfacePointLocalToMyFrame = surfaceFrame.Inverse() * otherSurfaceCenter;
float dot = myWorldNormal.Dot(otherWorldNormal);
if (dot > -0.99) continue; // Surface is pointing opposite to ours

View file

@ -19,7 +19,7 @@ struct PartConstructParams {
glm::vec3 position;
glm::vec3 rotation;
glm::vec3 size;
Data::Color3 color;
Color3 color;
bool anchored = false;
bool locked = false;
@ -49,10 +49,10 @@ protected:
public:
const static InstanceType TYPE;
Data::Vector3 velocity;
Data::CFrame cframe;
Vector3 velocity;
CFrame cframe;
glm::vec3 size;
Data::Color3 color;
Color3 color;
float transparency = 0.f;
bool selected = false;
@ -76,11 +76,11 @@ public:
static inline InstanceRef CreateGeneric() { return std::make_shared<Part>(); };
virtual const InstanceType* GetClass() override;
inline Data::Vector3 position() { return cframe.Position(); }
inline Vector3 position() { return cframe.Position(); }
void MakeJoints();
void BreakJoints();
// Calculate size of axis-aligned bounding box
Data::Vector3 GetAABB();
Vector3 GetAABB();
};

View file

@ -112,7 +112,7 @@ void Workspace::PhysicsStep(float deltaTime) {
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
const rp::Transform& transform = part->rigidBody->getTransform();
part->cframe = Data::CFrame(transform);
part->cframe = CFrame(transform);
part->velocity = part->rigidBody->getLinearVelocity();
}
}

View file

@ -131,7 +131,7 @@ void renderParts() {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
if (part->transparency > 0.00001) {
float distance = glm::length(glm::vec3(Data::Vector3(camera.cameraPos) - part->position()));
float distance = glm::length(glm::vec3(Vector3(camera.cameraPos) - part->position()));
sorted[distance] = part;
} else {
glm::mat4 model = part->cframe;
@ -264,7 +264,7 @@ void renderHandles() {
identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f));
for (auto face : HandleFace::Faces) {
Data::CFrame cframe = editorToolHandles->GetCFrameOfHandle(face);
CFrame cframe = editorToolHandles->GetCFrameOfHandle(face);
glm::vec4 screenPos = projection * view * glm::vec4((glm::vec3)cframe.Position(), 1.0f);
if (screenPos.z < 0) continue;
@ -310,7 +310,7 @@ void renderAABB() {
for (InstanceRef inst : gWorkspace()->GetChildren()) {
if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
glm::mat4 model = Data::CFrame::IDENTITY + part->cframe.Position();
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());
ghostShader->set("model", model);
@ -436,7 +436,7 @@ void renderRotationArcs() {
for (HandleFace face : HandleFace::Faces) {
if (glm::any(glm::lessThan(face.normal, glm::vec3(0)))) continue;
glm::mat4 model = part->cframe * Data::CFrame(glm::vec3(0), face.normal, glm::vec3(0, 1.01, 0.1));
glm::mat4 model = part->cframe * CFrame(glm::vec3(0), face.normal, glm::vec3(0, 1.01, 0.1));
handleShader->set("model", model);
float radius = glm::max(part->size.x, part->size.y, part->size.z) / 2.f + 2.f;

View file

@ -1,7 +1,7 @@
#include "surface.h"
#include "datatypes/vector.h"
Data::Vector3 FACE_NORMALS[6] = {
Vector3 FACE_NORMALS[6] = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 },
@ -10,7 +10,7 @@ Data::Vector3 FACE_NORMALS[6] = {
{ 0, 0, -1 },
};
NormalId faceFromNormal(Data::Vector3 normal) {
NormalId faceFromNormal(Vector3 normal) {
for (int face = 0; face < 6; face++) {
if (normal.Dot(FACE_NORMALS[face]) > 0.99)
return (NormalId)face;
@ -18,6 +18,6 @@ NormalId faceFromNormal(Data::Vector3 normal) {
return (NormalId)-1;
}
Data::Vector3 normalFromFace(NormalId face) {
Vector3 normalFromFace(NormalId face) {
return FACE_NORMALS[face];
}

View file

@ -18,6 +18,6 @@ enum SurfaceType {
SurfaceUniversal = 5,
};
namespace Data { class Vector3; }
NormalId faceFromNormal(Data::Vector3);
Data::Vector3 normalFromFace(NormalId);
namespace Data { class Vector3; } using Data::Vector3;
NormalId faceFromNormal(Vector3);
Vector3 normalFromFace(NormalId);

View file

@ -14,7 +14,7 @@
#define PI 3.14159
static Data::CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0, 1));
static CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0, 1));
MainGLWidget::MainGLWidget(QWidget* parent): QOpenGLWidget(parent) {
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
@ -66,7 +66,7 @@ void MainGLWidget::handleCameraRotate(QMouseEvent* evt) {
}
static Data::Vector3 orthoVecs[6] {
static Vector3 orthoVecs[6] {
{1, 0, 0},
{-1, 0, 0},
{0, 1, 0},
@ -77,12 +77,12 @@ static Data::Vector3 orthoVecs[6] {
// Snaps CFrame to the neareest 90 degree angle
// https://gamedev.stackexchange.com/a/183342
Data::CFrame snapCFrame(Data::CFrame frame) {
Data::Vector3 closestVec1{0, 0, 0};
CFrame snapCFrame(CFrame frame) {
Vector3 closestVec1{0, 0, 0};
float closest1 = 0.f;
// Primary vector
for (Data::Vector3 vec : orthoVecs) {
for (Vector3 vec : orthoVecs) {
float closeness = glm::dot((glm::vec3)frame.LookVector(), (glm::vec3)vec);
if (closeness > closest1) {
closest1 = closeness;
@ -90,11 +90,11 @@ Data::CFrame snapCFrame(Data::CFrame frame) {
}
}
Data::Vector3 closestVec2{0, 0, 0};
Vector3 closestVec2{0, 0, 0};
float closest2 = 0.f;
// Second vector
for (Data::Vector3 vec : orthoVecs) {
for (Vector3 vec : orthoVecs) {
// Guard against accidental linear dependency
if (vec == closestVec1) continue;
@ -105,16 +105,16 @@ Data::CFrame snapCFrame(Data::CFrame frame) {
}
}
// Data::Vector3 thirdVec = closestVec1.Cross(closestVec2);
return Data::CFrame(frame.Position(), frame.Position() + closestVec1, closestVec2);
// Vector3 thirdVec = closestVec1.Cross(closestVec2);
return CFrame(frame.Position(), frame.Position() + closestVec1, closestVec2);
}
bool isMouseDragging = false;
std::weak_ptr<Part> draggingObject;
std::optional<HandleFace> draggingHandle;
Data::Vector3 initialHitPos;
Data::Vector3 initialHitNormal;
Data::CFrame initialFrame;
Vector3 initialHitPos;
Vector3 initialHitNormal;
CFrame initialFrame;
void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
if (!isMouseDragging || draggingObject.expired() || mainWindow()->selectedTool >= TOOL_SMOOTH) return;
@ -127,32 +127,32 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
if (!rayHit) return;
Data::CFrame targetFrame = partFromBody(rayHit->body)->cframe;
Data::Vector3 surfaceNormal = targetFrame.Inverse().Rotation() * rayHit->worldNormal;
Data::Vector3 inverseSurfaceNormal = Data::Vector3::ONE - surfaceNormal.Abs();
CFrame targetFrame = partFromBody(rayHit->body)->cframe;
Vector3 surfaceNormal = targetFrame.Inverse().Rotation() * rayHit->worldNormal;
Vector3 inverseSurfaceNormal = Vector3::ONE - surfaceNormal.Abs();
glm::vec3 partSize = partFromBody(rayHit->body)->size;
Data::Vector3 tFormedHitPos = targetFrame * ((targetFrame.Inverse() * initialHitPos) * inverseSurfaceNormal);
Data::Vector3 tFormedInitialPos = targetFrame * ((targetFrame.Inverse() * initialFrame.Position()) * inverseSurfaceNormal);
Data::Vector3 vec = rayHit->worldPoint + (tFormedInitialPos - tFormedHitPos);
Vector3 tFormedHitPos = targetFrame * ((targetFrame.Inverse() * initialHitPos) * inverseSurfaceNormal);
Vector3 tFormedInitialPos = targetFrame * ((targetFrame.Inverse() * initialFrame.Position()) * inverseSurfaceNormal);
Vector3 vec = rayHit->worldPoint + (tFormedInitialPos - tFormedHitPos);
// The part being dragged's frame local to the hit target's frame, but without its position component
// To find a world vector local to the new frame, use newFrame, not localFrame, as localFrame is localFrame is local to targetFrame in itself
Data::CFrame localFrame = (targetFrame.Inverse() * (draggingObject.lock()->cframe.Rotation() + vec));
CFrame localFrame = (targetFrame.Inverse() * (draggingObject.lock()->cframe.Rotation() + vec));
// Snap axis
localFrame = snapCFrame(localFrame);
// Snap to studs
Data::Vector3 draggingPartSize = draggingObject.lock()->size;
glm::vec3 inverseNormalPartSize = (Data::Vector3)(partSize - glm::vec3(localFrame.Rotation() * draggingPartSize)) * inverseSurfaceNormal / 2.f;
Vector3 draggingPartSize = draggingObject.lock()->size;
glm::vec3 inverseNormalPartSize = (Vector3)(partSize - glm::vec3(localFrame.Rotation() * draggingPartSize)) * inverseSurfaceNormal / 2.f;
if (snappingFactor() > 0)
localFrame = localFrame.Rotation() + glm::round(glm::vec3(localFrame.Position() * inverseSurfaceNormal - inverseNormalPartSize) / snappingFactor()) * snappingFactor() + inverseNormalPartSize
+ localFrame.Position() * surfaceNormal.Abs();
Data::CFrame newFrame = targetFrame * localFrame;
CFrame newFrame = targetFrame * localFrame;
// Unsink the object
// Get the normal of the surface relative to the part's frame, and get the size along that vector
Data::Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * draggingObject.lock()->size / 2);
Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * draggingObject.lock()->size / 2);
draggingObject.lock()->cframe = newFrame + unsinkOffset;
@ -179,10 +179,10 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
pointDir = glm::normalize(pointDir);
Data::CFrame handleCFrame = editorToolHandles->GetCFrameOfHandle(draggingHandle.value());
CFrame handleCFrame = editorToolHandles->GetCFrameOfHandle(draggingHandle.value());
// Current frame. Identity frame if worldMode == true, selected object's frame if worldMode == false
Data::CFrame frame = editorToolHandles->worldMode ? Data::CFrame::IDENTITY + part->position() : part->cframe.Rotation();
CFrame frame = editorToolHandles->worldMode ? CFrame::IDENTITY + part->position() : part->cframe.Rotation();
// Segment from axis stretching -4096 to +4096 rel to handle's position
glm::vec3 axisSegment0 = handleCFrame.Position() + (-handleCFrame.LookVector() * 4096.0f);
@ -203,7 +203,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
glm::vec3 diff = centerPoint - (glm::vec3)part->position();
if (snappingFactor()) diff = frame.Rotation() * (glm::round(glm::vec3(frame.Inverse().Rotation() * diff) / snappingFactor()) * snappingFactor());
Data::Vector3 oldSize = part->size;
Vector3 oldSize = part->size;
switch (mainWindow()->selectedTool) {
case TOOL_MOVE: {
@ -249,7 +249,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
part->UpdateProperty("Position");
part->UpdateProperty("Size");
sendPropertyUpdatedSignal(part, "Position", part->position());
sendPropertyUpdatedSignal(part, "Size", Data::Vector3(part->size));
sendPropertyUpdatedSignal(part, "Size", Vector3(part->size));
}
// Also implemented based on Godot: [c7ea8614](godot/editor/plugins/canvas_item_editor_plugin.cpp#L1490)
@ -288,7 +288,7 @@ void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) {
glm::vec3 angles = glm::abs(draggingHandle->normal) * sign * glm::vec3(angle);
part->cframe = initialFrame * Data::CFrame::FromEulerAnglesXYZ(-angles);
part->cframe = initialFrame * CFrame::FromEulerAnglesXYZ(-angles);
gWorkspace()->SyncPartPhysics(part);
part->UpdateProperty("Rotation");
@ -377,7 +377,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
// Handle surface tool
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
Data::Vector3 localNormal = part->cframe.Inverse().Rotation() * rayHit->worldNormal;
Vector3 localNormal = part->cframe.Inverse().Rotation() * rayHit->worldNormal;
NormalId face = faceFromNormal(localNormal);
SurfaceType surface = SurfaceType(mainWindow()->selectedTool - TOOL_SMOOTH);

View file

@ -51,8 +51,8 @@ public:
Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect();
if (isComposite) {
if (meta.type == &Data::Vector3::TYPE) {
Data::Vector3 vector = currentValue.get<Data::Vector3>();
if (meta.type == &Vector3::TYPE) {
Vector3 vector = currentValue.get<Vector3>();
float value = componentName == "X" ? vector.X() : componentName == "Y" ? vector.Y() : componentName == "Z" ? vector.Z() : 0;
QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
@ -85,10 +85,10 @@ public:
lineEdit->setText(QString::fromStdString(currentValue.get<Data::String>()));
return lineEdit;
} else if (meta.type == &Data::Color3::TYPE) {
} else if (meta.type == &Color3::TYPE) {
QColorDialog* colorDialog = new QColorDialog(parent->window());
Data::Color3 color = currentValue.get<Data::Color3>();
Color3 color = currentValue.get<Color3>();
colorDialog->setCurrentColor(QColor::fromRgbF(color.R(), color.G(), color.B()));
return colorDialog;
@ -117,8 +117,8 @@ public:
Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect();
if (isComposite) {
if (meta.type == &Data::Vector3::TYPE) {
Data::Vector3 vector = currentValue.get<Data::Vector3>();
if (meta.type == &Vector3::TYPE) {
Vector3 vector = currentValue.get<Vector3>();
float value = componentName == "X" ? vector.X() : componentName == "Y" ? vector.Y() : componentName == "Z" ? vector.Z() : 0;
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
@ -142,10 +142,10 @@ public:
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
lineEdit->setText(QString::fromStdString((std::string)currentValue.get<Data::String>()));
} else if (meta.type == &Data::Color3::TYPE) {
} else if (meta.type == &Color3::TYPE) {
QColorDialog* colorDialog = dynamic_cast<QColorDialog*>(editor);
Data::Color3 color = currentValue.get<Data::Color3>();
Color3 color = currentValue.get<Color3>();
colorDialog->setCurrentColor(QColor::fromRgbF(color.R(), color.G(), color.B()));
} else if (meta.type->fromString) {
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
@ -168,17 +168,17 @@ public:
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
if (isComposite) {
if (meta.type == &Data::Vector3::TYPE) {
if (meta.type == &Vector3::TYPE) {
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(editor);
float value = spinBox->value();
Data::Vector3 prev = inst->GetPropertyValue(propertyName).expect().get<Data::Vector3>();
Data::Vector3 newVector = componentName == "X" ? Data::Vector3(value, prev.Y(), prev.Z())
: componentName == "Y" ? Data::Vector3(prev.X(), value, prev.Z())
: componentName == "Z" ? Data::Vector3(prev.X(), prev.Y(), value) : prev;
Vector3 prev = inst->GetPropertyValue(propertyName).expect().get<Vector3>();
Vector3 newVector = componentName == "X" ? Vector3(value, prev.Y(), prev.Z())
: componentName == "Y" ? Vector3(prev.X(), value, prev.Z())
: componentName == "Z" ? Vector3(prev.X(), prev.Y(), value) : prev;
inst->SetPropertyValue(propertyName, newVector).expect();
view->rebuildCompositeProperty(view->itemFromIndex(index.parent()), &Data::Vector3::TYPE, newVector);
view->rebuildCompositeProperty(view->itemFromIndex(index.parent()), &Vector3::TYPE, newVector);
return;
}
@ -200,11 +200,11 @@ public:
inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString())).expect();
model->setData(index, lineEdit->text());
} else if (meta.type == &Data::Color3::TYPE) {
} else if (meta.type == &Color3::TYPE) {
QColorDialog* colorDialog = dynamic_cast<QColorDialog*>(editor);
QColor color = colorDialog->currentColor();
Data::Color3 color3(color.redF(), color.greenF(), color.blueF());
Color3 color3(color.redF(), color.greenF(), color.blueF());
inst->SetPropertyValue(propertyName, color3).expect();
model->setData(index, QString::fromStdString(color3.ToString()), Qt::DisplayRole);
model->setData(index, color, Qt::DecorationRole);
@ -296,7 +296,7 @@ void PropertiesView::setSelected(std::optional<InstanceRef> instance) {
PropertyMeta meta = inst->GetPropertyMeta(property).expect();
Data::Variant currentValue = inst->GetPropertyValue(property).expect();
// if (meta.type == &Data::CFrame::TYPE) continue;
// if (meta.type == &CFrame::TYPE) continue;
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setFlags(item->flags() | Qt::ItemIsEditable | Qt::ItemIsSelectable);
@ -304,21 +304,21 @@ void PropertiesView::setSelected(std::optional<InstanceRef> instance) {
if (meta.type == &Data::Bool::TYPE) {
item->setCheckState(1, (bool)currentValue.get<Data::Bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
} else if (meta.type == &Data::Color3::TYPE) {
Data::Color3 color = currentValue.get<Data::Color3>();
} else if (meta.type == &Color3::TYPE) {
Color3 color = currentValue.get<Color3>();
item->setData(1, Qt::DecorationRole, QColor::fromRgbF(color.R(), color.G(), color.B()));
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
} else if (meta.type == &Data::Vector3::TYPE) {
Data::Vector3 vector = currentValue.get<Data::Vector3>();
} else if (meta.type == &Vector3::TYPE) {
Vector3 vector = currentValue.get<Vector3>();
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
} else if (meta.type == &Data::CFrame::TYPE) {
Data::Vector3 vector = currentValue.get<Data::CFrame>().Position();
} else if (meta.type == &CFrame::TYPE) {
Vector3 vector = currentValue.get<CFrame>().Position();
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
} else {
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
}
if (meta.type != &Data::Color3::TYPE && (!meta.type->fromString || meta.flags & PROP_READONLY)) {
if (meta.type != &Color3::TYPE && (!meta.type->fromString || meta.flags & PROP_READONLY)) {
item->setDisabled(true);
}
@ -351,11 +351,11 @@ void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) {
}
void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const Data::TypeInfo* type, Data::Variant value) {
if (type == &Data::Vector3::TYPE) {
if (type == &Vector3::TYPE) {
// https://forum.qt.io/post/266837
foreach(auto i, item->takeChildren()) delete i;
Data::Vector3 vector = value.get<Data::Vector3>();
Vector3 vector = value.get<Vector3>();
item->setData(1, Qt::DisplayRole, QString::fromStdString(value.ToString()));
QTreeWidgetItem* xItem = new QTreeWidgetItem;
@ -385,7 +385,7 @@ void PropertiesView::onPropertyUpdated(InstanceRef inst, std::string property, D
PropertyMeta meta = inst->GetPropertyMeta(property).expect();
Data::Variant currentValue = inst->GetPropertyValue(property).expect();
if (meta.type == &Data::CFrame::TYPE) return;
if (meta.type == &CFrame::TYPE) return;
for (int categoryItemIdx = 0; categoryItemIdx < topLevelItemCount(); categoryItemIdx++) {
QTreeWidgetItem* categoryItem = topLevelItem(categoryItemIdx);
@ -396,18 +396,18 @@ void PropertiesView::onPropertyUpdated(InstanceRef inst, std::string property, D
if (meta.type == &Data::Bool::TYPE) {
item->setCheckState(1, (bool)currentValue.get<Data::Bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
} else if (meta.type == &Data::Color3::TYPE) {
Data::Color3 color = currentValue.get<Data::Color3>();
} else if (meta.type == &Color3::TYPE) {
Color3 color = currentValue.get<Color3>();
item->setData(1, Qt::DecorationRole, QColor::fromRgbF(color.R(), color.G(), color.B()));
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
} else if (meta.type == &Data::Vector3::TYPE) {
Data::Vector3 vector = currentValue.get<Data::Vector3>();
} else if (meta.type == &Vector3::TYPE) {
Vector3 vector = currentValue.get<Vector3>();
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
} else {
item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString()));
}
if (meta.type != &Data::Color3::TYPE && (!meta.type->fromString || meta.flags & PROP_READONLY)) {
if (meta.type != &Color3::TYPE && (!meta.type->fromString || meta.flags & PROP_READONLY)) {
item->setDisabled(true);
}