diff --git a/core/src/datatypes/vector.cpp b/core/src/datatypes/vector.cpp index 0444df6..24b7fc8 100644 --- a/core/src/datatypes/vector.cpp +++ b/core/src/datatypes/vector.cpp @@ -3,6 +3,7 @@ #include #include "meta.h" // IWYU pragma: keep +Data::Vector3::Vector3() : vector(glm::vec3(0, 0, 0)) {}; Data::Vector3::Vector3(const glm::vec3& src) : vector(src) {}; Data::Vector3::Vector3(const rp::Vector3& src) : vector(glm::vec3(src.x, src.y, src.z)) {}; Data::Vector3::Vector3(float x, const float y, float z) : vector(glm::vec3(x, y, z)) {}; diff --git a/core/src/datatypes/vector.h b/core/src/datatypes/vector.h index cb1ef9a..3e504de 100644 --- a/core/src/datatypes/vector.h +++ b/core/src/datatypes/vector.h @@ -12,6 +12,7 @@ namespace Data { glm::vec3 vector; public: + Vector3(); Vector3(float x, float y, float z); Vector3(const glm::vec3&); Vector3(const rp::Vector3&); diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index ddb0c73..65c079f 100644 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -107,6 +107,9 @@ Data::CFrame snapCFrame(Data::CFrame frame) { bool isMouseDragging = false; std::optional> draggingObject; std::optional draggingHandle; +Data::Vector3 initialHitPos; +Data::Vector3 initialHitNormal; +Data::CFrame initialFrame; void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { if (!isMouseDragging || !draggingObject || mainWindow()->selectedTool >= TOOL_SMOOTH) return; @@ -119,10 +122,13 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { if (!rayHit) return; - glm::vec3 partSize = partFromBody(rayHit->body)->size; - Data::Vector3 vec = rayHit->worldPoint; Data::CFrame targetFrame = partFromBody(rayHit->body)->cframe; Data::Vector3 surfaceNormal = targetFrame.Inverse().Rotation() * rayHit->worldNormal; + Data::Vector3 inverseSurfaceNormal = Data::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); // 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)); @@ -132,7 +138,6 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { // Snap to studs Data::Vector3 draggingPartSize = draggingObject->lock()->size; - Data::Vector3 inverseSurfaceNormal = Data::Vector3::ONE - surfaceNormal.Abs(); glm::vec3 inverseNormalPartSize = (Data::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 @@ -146,6 +151,7 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { draggingObject->lock()->cframe = newFrame + unsinkOffset; + gWorkspace()->SyncPartPhysics(draggingObject->lock()); sendPropertyUpdatedSignal(draggingObject->lock(), "Position", draggingObject->lock()->position()); } @@ -231,7 +237,6 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) { // Also implemented based on Godot: [c7ea8614](godot/editor/plugins/canvas_item_editor_plugin.cpp#L1490) glm::vec2 startPoint; -Data::CFrame initialFrame = Data::CFrame::IDENTITY; void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) { if (!isMouseDragging || !draggingHandle || !editorToolHandles->adornee || !editorToolHandles->active) return; @@ -348,6 +353,9 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) { if (!rayHit || !partFromBody(rayHit->body)) return; std::shared_ptr part = partFromBody(rayHit->body); if (part->locked) return; + initialFrame = part->cframe; + initialHitPos = rayHit->worldPoint; + initialHitNormal = rayHit->worldNormal; // Handle surface tool if (mainWindow()->selectedTool >= TOOL_SMOOTH) {