diff --git a/core/src/objects/handles.cpp b/core/src/objects/handles.cpp index 7671f3e..5c07fb3 100644 --- a/core/src/objects/handles.cpp +++ b/core/src/objects/handles.cpp @@ -16,6 +16,8 @@ HandleFace HandleFace::ZPos(4, glm::vec3(0,0,1)); HandleFace HandleFace::ZNeg(5, glm::vec3(0,0,-1)); std::array 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)); + // Shitty solution static rp3d::PhysicsCommon common; static rp3d::PhysicsWorld* world = common.createPhysicsWorld(); @@ -39,14 +41,18 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) { Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee->lock()->position() : adornee->lock()->cframe; + Data::Vector3 handleNormal = face.normal; + if (nixAxes) + handleNormal = XYZToZXY * face.normal; + // We don't want this to align with local * face.normal, or else we have problems. glm::vec3 upAxis(0, 0, 1); - if (glm::abs(glm::dot(glm::vec3(localFrame.Rotation() * face.normal), upAxis)) > 0.9999f) + if (glm::abs(glm::dot(glm::vec3(localFrame.Rotation() * handleNormal), upAxis)) > 0.9999f) upAxis = glm::vec3(0, 1, 0); Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee->lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee->lock()->size * 0.5f); - Data::Vector3 handlePos = localFrame * (handleOffset * face.normal); - Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -face.normal, upAxis); + Data::Vector3 handlePos = localFrame * (handleOffset * handleNormal); + Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis); return cframe; } diff --git a/core/src/objects/handles.h b/core/src/objects/handles.h index 159b206..86a18ba 100644 --- a/core/src/objects/handles.h +++ b/core/src/objects/handles.h @@ -34,6 +34,7 @@ class Handles : public Instance { public: const static InstanceType TYPE; + bool nixAxes = false; // XYZ -> ZXY, used with rotation bool active; std::optional> adornee; HandlesType handlesType; diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index de4ea19..df73bb4 100644 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -37,6 +37,8 @@ #include "mainglwidget.h" #include "math_helper.h" +static Data::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); setMouseTracking(true); @@ -259,8 +261,20 @@ void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) { glm::vec2 initVec = glm::normalize(startPoint - (glm::vec2)screenPos); glm::vec2 destVec = glm::normalize(destPoint - (glm::vec2)screenPos); float angle = atan2f(initVec.x * destVec.y - initVec.y * destVec.x, initVec.x * destVec.x + initVec.y * destVec.y); - - part->cframe = part->cframe * Data::CFrame::FromEulerAnglesXYZ(glm::vec3(0, -angle, 0)); + + // Yes, it's messy. But it works so I don't wanna hear it. + // Maybe I'll clean it up next week. + // TODO: ? + glm::vec4 pos1 = projection * view * glm::vec4((glm::vec3)part->cframe.Position(), 1.f); + pos1 /= pos1.w; + glm::vec4 otherVec = projection * view * glm::vec4((glm::vec3)(part->cframe * glm::abs(draggingHandle->normal)), 1.f); + otherVec /= otherVec.w; + glm::vec4 signVec = glm::normalize(otherVec - pos1); + float sign = glm::sign(signVec.z); + + glm::vec3 angles = glm::abs(draggingHandle->normal) * -sign * glm::vec3(angle); + + part->cframe = part->cframe * Data::CFrame::FromEulerAnglesXYZ(-angles); syncPartPhysics(std::dynamic_pointer_cast(editorToolHandles->adornee->lock())); } diff --git a/editor/mainwindow.cpp b/editor/mainwindow.cpp index 0becd9a..6f320fe 100644 --- a/editor/mainwindow.cpp +++ b/editor/mainwindow.cpp @@ -323,11 +323,8 @@ void MainWindow::updateToolbars() { ui->actionGridSnap05->setChecked(snappingMode == GridSnappingMode::SNAP_05_STUDS); ui->actionGridSnapOff->setChecked(snappingMode == GridSnappingMode::SNAP_OFF); - // editorToolHandles->worldMode = false; - if (selectedTool == SelectedTool::SCALE) - editorToolHandles->worldMode = false; - else - editorToolHandles->worldMode = worldSpaceTransforms; + editorToolHandles->worldMode = selectedTool == SelectedTool::SCALE ? false : worldSpaceTransforms; + editorToolHandles->nixAxes = selectedTool == SelectedTool::ROTATE; editorToolHandles->active = selectedTool != SelectedTool::SELECT; editorToolHandles->handlesType =