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) { , rotation(rotation) {
} }
Data::CFrame::CFrame(Data::Vector3 position, glm::quat quat) Data::CFrame::CFrame(Vector3 position, glm::quat quat)
: translation(position) : translation(position)
, rotation(quat) { , 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())) { 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 // https://github.com/sgorsten/linalg/issues/29#issuecomment-743989030
Data::Vector3 f = (lookAt - position).Unit(); // Forward/Look Vector3 f = (lookAt - position).Unit(); // Forward/Look
Data::Vector3 u = up.Unit(); // Up Vector3 u = up.Unit(); // Up
Data::Vector3 s = f.Cross(u).Unit(); // Right Vector3 s = f.Cross(u).Unit(); // Right
u = s.Cross(f).Unit(); u = s.Cross(f).Unit();
return { s, u, -f }; 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) : translation(position)
, rotation(::lookAt(position, lookAt, up)) { , rotation(::lookAt(position, lookAt, up)) {
} }
@ -61,7 +61,7 @@ const Data::TypeInfo Data::CFrame::TYPE = {
.deserializer = &Data::CFrame::Deserialize, .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 { const Data::String Data::CFrame::ToString() const {
return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z()); 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)); return rp::Transform(glmToRp(translation), glmToRp(rotation));
} }
Data::Vector3 Data::CFrame::ToEulerAnglesXYZ() { Vector3 Data::CFrame::ToEulerAnglesXYZ() {
float x; float x;
float y; float y;
float z; float z;
glm::extractEulerAngleXYZ(glm::mat4(this->rotation), x, y, 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()); 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 { 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 }; 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; 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 }; 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; return *this + -vector;
} }

View file

@ -23,8 +23,8 @@ namespace Data {
CFrame(); 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(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(const rp::Transform&);
CFrame(Data::Vector3 position, glm::quat quat); CFrame(Vector3 position, glm::quat quat);
CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up = Data::Vector3(0, 1, 0)); CFrame(Vector3 position, Vector3 lookAt, Vector3 up = Vector3(0, 1, 0));
~CFrame(); ~CFrame();
static const CFrame IDENTITY; static const CFrame IDENTITY;
@ -53,12 +53,14 @@ namespace Data {
inline Vector3 LookVector() { return -glm::column(rotation, 2); } inline Vector3 LookVector() { return -glm::column(rotation, 2); }
Vector3 ToEulerAnglesXYZ(); Vector3 ToEulerAnglesXYZ();
static CFrame FromEulerAnglesXYZ(Data::Vector3); static CFrame FromEulerAnglesXYZ(Vector3);
// Operators // Operators
Data::CFrame operator *(Data::CFrame) const; Data::CFrame operator *(Data::CFrame) const;
Data::Vector3 operator *(Data::Vector3) const; Vector3 operator *(Vector3) const;
Data::CFrame operator +(Data::Vector3) const; Data::CFrame operator +(Vector3) const;
Data::CFrame operator -(Data::Vector3) const; Data::CFrame operator -(Vector3) const;
}; };
} }
using Data::CFrame;

View file

@ -35,3 +35,5 @@ namespace Data {
inline float B() const { return b; } 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()); // 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()); // return Color3::FromHex(node.text().get());
// } // }

View file

@ -55,6 +55,8 @@ namespace Data {
}; };
} }
using Data::Vector3;
inline void printVec(Data::Vector3 vec) { inline void printVec(Data::Vector3 vec) {
printf("(%f, %f, %f)\n", vec.X(), vec.Y(), vec.Z()); 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)); 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 }; 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 // Shitty solution
static rp3d::PhysicsCommon common; static rp3d::PhysicsCommon common;
@ -37,12 +37,12 @@ const InstanceType* Handles::GetClass() {
Handles::Handles(): Instance(&TYPE) { Handles::Handles(): Instance(&TYPE) {
} }
Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) { CFrame Handles::GetCFrameOfHandle(HandleFace face) {
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0)); 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) if (nixAxes)
handleNormal = XYZToZXY * face.normal; handleNormal = XYZToZXY * face.normal;
@ -52,21 +52,21 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
upAxis = glm::vec3(0, 1, 0); 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; 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); Vector3 handleOffset = this->worldMode ? ((Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Vector3(2.f + partSize * 0.5f);
Data::Vector3 handlePos = localFrame * (handleOffset * handleNormal); Vector3 handlePos = localFrame * (handleOffset * handleNormal);
Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis); CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis);
return cframe; return cframe;
} }
Data::CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos) { CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Vector3 newPos) {
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0)); 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::CFrame inverseFrame = localFrame.Inverse(); 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); 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 localPos = inverseFrame * newPos;
glm::vec3 newPartPos = newPos - localFrame.Rotation() * (handleOffset * face.normal); 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) { std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
for (HandleFace face : HandleFace::Faces) { for (HandleFace face : HandleFace::Faces) {
Data::CFrame cframe = GetCFrameOfHandle(face); CFrame cframe = GetCFrameOfHandle(face);
// Implement manual detection via boxes instead of... this shit // Implement manual detection via boxes instead of... this shit
// This code also hardly works, and is not good at all... Hooo nope. // This code also hardly works, and is not good at all... Hooo nope.
rp3d::RigidBody* body = world->createRigidBody(Data::CFrame::IDENTITY + cframe.Position()); rp3d::RigidBody* body = world->createRigidBody(CFrame::IDENTITY + cframe.Position());
body->addCollider(common.createBoxShape(cframe.Rotation() * Data::Vector3(HandleSize(face) / 2.f)), rp3d::Transform::identity()); body->addCollider(common.createBoxShape(cframe.Rotation() * Vector3(HandleSize(face) / 2.f)), rp3d::Transform::identity());
rp3d::RaycastInfo info; rp3d::RaycastInfo info;
if (body->raycast(ray, info)) { if (body->raycast(ray, info)) {
@ -93,7 +93,7 @@ std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
return std::nullopt; return std::nullopt;
} }
Data::Vector3 Handles::HandleSize(HandleFace face) { Vector3 Handles::HandleSize(HandleFace face) {
if (handlesType == HandlesType::MoveHandles) if (handlesType == HandlesType::MoveHandles)
return glm::vec3(0.5f, 0.5f, 2.f); return glm::vec3(0.5f, 0.5f, 2.f);
return glm::vec3(1,1,1); return glm::vec3(1,1,1);

View file

@ -46,9 +46,9 @@ public:
// World-space handles vs local-space handles // World-space handles vs local-space handles
bool worldMode = false; bool worldMode = false;
Data::CFrame GetCFrameOfHandle(HandleFace face); CFrame GetCFrameOfHandle(HandleFace face);
Data::CFrame PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos); CFrame PartCFrameFromHandlePos(HandleFace face, Vector3 newPos);
Data::Vector3 HandleSize(HandleFace face); Vector3 HandleSize(HandleFace face);
std::optional<HandleFace> RaycastHandle(rp3d::Ray ray); std::optional<HandleFace> RaycastHandle(rp3d::Ray ray);
static inline std::shared_ptr<Handles> New() { return std::make_shared<Handles>(); }; 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), .updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C0", { }}, { "C0", {
.backingField = &c0, .backingField = &c0,
.type = &Data::CFrame::TYPE, .type = &CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(), .codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this), .updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C1", { }}, { "C1", {
.backingField = &c1, .backingField = &c1,
.type = &Data::CFrame::TYPE, .type = &CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(), .codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this), .updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, }},
} }

View file

@ -25,8 +25,8 @@ public:
std::weak_ptr<Part> part0; std::weak_ptr<Part> part0;
std::weak_ptr<Part> part1; std::weak_ptr<Part> part1;
Data::CFrame c0; CFrame c0;
Data::CFrame c1; CFrame c1;
JointInstance(const InstanceType*); JointInstance(const InstanceType*);
~JointInstance(); ~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 // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
// used to be rather than specifying an anchor rotation, so whatever. // used to be rather than specifying an anchor rotation, so whatever.
Data::CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0); CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
part1.lock()->cframe = newFrame; part1.lock()->cframe = newFrame;
workspace->SyncPartPhysics(part1.lock()); 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 // Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
// used to be rather than specifying an anchor rotation, so whatever. // used to be rather than specifying an anchor rotation, so whatever.
Data::CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0); CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
part1.lock()->cframe = newFrame; part1.lock()->cframe = newFrame;
workspace->SyncPartPhysics(part1.lock()); workspace->SyncPartPhysics(part1.lock());

View file

@ -14,8 +14,6 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
using Data::Vector3;
// template <typename T, typename U> // template <typename T, typename U>
// constexpr FieldCodec fieldCodecOf() { // constexpr FieldCodec fieldCodecOf() {
// return FieldCodec { // return FieldCodec {
@ -31,11 +29,11 @@ using Data::Vector3;
constexpr FieldCodec cframePositionCodec() { constexpr FieldCodec cframePositionCodec() {
return FieldCodec { return FieldCodec {
.write = [](Data::Variant source, void* destination) { .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>(); *cframe = cframe->Rotation() + source.get<Vector3>();
}, },
.read = [](void* source) -> Data::Variant { .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() { constexpr FieldCodec cframeRotationCodec() {
return FieldCodec { return FieldCodec {
.write = [](Data::Variant source, void* destination) { .write = [](Data::Variant source, void* destination) {
Data::CFrame* cframe = static_cast<Data::CFrame*>(destination); CFrame* cframe = static_cast<CFrame*>(destination);
*cframe = Data::CFrame::FromEulerAnglesXYZ(source.get<Vector3>()) + cframe->Position(); *cframe = CFrame::FromEulerAnglesXYZ(source.get<Vector3>()) + cframe->Position();
}, },
.read = [](void* source) -> Data::Variant { .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; 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) { size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
this->memberMap = std::make_unique<MemberMap>(MemberMap { this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap), .super = std::move(this->memberMap),
@ -97,12 +95,12 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame::Fr
}}, { "Velocity", { }}, { "Velocity", {
.backingField = &velocity, .backingField = &velocity,
.type = &Vector3::TYPE, .type = &Vector3::TYPE,
.codec = fieldCodecOf<Data::Vector3>(), .codec = fieldCodecOf<Vector3>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this), .updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "CFrame", { }}, { "CFrame", {
.backingField = &cframe, .backingField = &cframe,
.type = &Data::CFrame::TYPE, .type = &CFrame::TYPE,
.codec = fieldCodecOf<Data::CFrame>(), .codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this), .updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "Size", { }}, { "Size", {
.backingField = &size, .backingField = &size,
@ -112,8 +110,8 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame::Fr
.category = PROP_CATEGORY_PART, .category = PROP_CATEGORY_PART,
}}, { "Color", { }}, { "Color", {
.backingField = &color, .backingField = &color,
.type = &Data::Color3::TYPE, .type = &Color3::TYPE,
.codec = fieldCodecOf<Data::Color3>(), .codec = fieldCodecOf<Color3>(),
.category = PROP_CATEGORY_APPEARENCE, .category = PROP_CATEGORY_APPEARENCE,
}}, { "Transparency", { }}, { "Transparency", {
.backingField = &transparency, .backingField = &transparency,
@ -191,7 +189,7 @@ void Part::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std
void Part::onUpdated(std::string property) { void Part::onUpdated(std::string property) {
// Reset velocity // Reset velocity
if (property != "Velocity") if (property != "Velocity")
velocity = Data::Vector3::ZERO; velocity = Vector3::ZERO;
if (workspace()) if (workspace())
workspace().value()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(this->shared_from_this())); 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 min(0, 0, 0);
Vector3 max(0, 0, 0); Vector3 max(0, 0, 0);
for (Vector3 vert : verts) { 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); expandMaxExtents(&min, &max, worldVert);
} }
@ -240,7 +238,7 @@ void Part::BreakJoints() {
} }
} }
static Data::Vector3 FACES[6] = { static Vector3 FACES[6] = {
{1, 0, 0}, {1, 0, 0},
{0, 1, 0}, {0, 1, 0},
{0, 0, 1}, {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 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(); std::shared_ptr<Part> otherPart = obj->CastTo<Part>().expect();
for (Data::Vector3 myFace : FACES) { for (Vector3 myFace : FACES) {
Data::Vector3 myWorldNormal = cframe.Rotation() * myFace; 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 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
Data::CFrame surfaceFrame(cframe.Position(), cframe * (myFace * size), validUp); CFrame surfaceFrame(cframe.Position(), cframe * (myFace * size), validUp);
for (Data::Vector3 otherFace : FACES) { for (Vector3 otherFace : FACES) {
Data::Vector3 otherWorldNormal = otherPart->cframe.Rotation() * otherFace; Vector3 otherWorldNormal = otherPart->cframe.Rotation() * otherFace;
Data::Vector3 otherSurfaceCenter = otherPart->cframe * (otherFace * otherPart->size); Vector3 otherSurfaceCenter = otherPart->cframe * (otherFace * otherPart->size);
Data::Vector3 surfacePointLocalToMyFrame = surfaceFrame.Inverse() * otherSurfaceCenter; Vector3 surfacePointLocalToMyFrame = surfaceFrame.Inverse() * otherSurfaceCenter;
float dot = myWorldNormal.Dot(otherWorldNormal); float dot = myWorldNormal.Dot(otherWorldNormal);
if (dot > -0.99) continue; // Surface is pointing opposite to ours if (dot > -0.99) continue; // Surface is pointing opposite to ours

View file

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

View file

@ -131,7 +131,7 @@ void renderParts() {
if (inst->GetClass()->className != "Part") continue; if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst); std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
if (part->transparency > 0.00001) { 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; sorted[distance] = part;
} else { } else {
glm::mat4 model = part->cframe; glm::mat4 model = part->cframe;
@ -264,7 +264,7 @@ void renderHandles() {
identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f)); identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f));
for (auto face : HandleFace::Faces) { 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); glm::vec4 screenPos = projection * view * glm::vec4((glm::vec3)cframe.Position(), 1.0f);
if (screenPos.z < 0) continue; if (screenPos.z < 0) continue;
@ -310,7 +310,7 @@ void renderAABB() {
for (InstanceRef inst : gWorkspace()->GetChildren()) { for (InstanceRef inst : gWorkspace()->GetChildren()) {
if (inst->GetClass()->className != "Part") continue; if (inst->GetClass()->className != "Part") continue;
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst); 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()); 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()); model = glm::scale(model, (glm::vec3)part->GetAABB());
ghostShader->set("model", model); ghostShader->set("model", model);
@ -436,7 +436,7 @@ void renderRotationArcs() {
for (HandleFace face : HandleFace::Faces) { for (HandleFace face : HandleFace::Faces) {
if (glm::any(glm::lessThan(face.normal, glm::vec3(0)))) continue; 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); handleShader->set("model", model);
float radius = glm::max(part->size.x, part->size.y, part->size.z) / 2.f + 2.f; 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 "surface.h"
#include "datatypes/vector.h" #include "datatypes/vector.h"
Data::Vector3 FACE_NORMALS[6] = { Vector3 FACE_NORMALS[6] = {
{ 1, 0, 0 }, { 1, 0, 0 },
{ 0, 1, 0 }, { 0, 1, 0 },
{ 0, 0, 1 }, { 0, 0, 1 },
@ -10,7 +10,7 @@ Data::Vector3 FACE_NORMALS[6] = {
{ 0, 0, -1 }, { 0, 0, -1 },
}; };
NormalId faceFromNormal(Data::Vector3 normal) { NormalId faceFromNormal(Vector3 normal) {
for (int face = 0; face < 6; face++) { for (int face = 0; face < 6; face++) {
if (normal.Dot(FACE_NORMALS[face]) > 0.99) if (normal.Dot(FACE_NORMALS[face]) > 0.99)
return (NormalId)face; return (NormalId)face;
@ -18,6 +18,6 @@ NormalId faceFromNormal(Data::Vector3 normal) {
return (NormalId)-1; return (NormalId)-1;
} }
Data::Vector3 normalFromFace(NormalId face) { Vector3 normalFromFace(NormalId face) {
return FACE_NORMALS[face]; return FACE_NORMALS[face];
} }

View file

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

View file

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

View file

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