From 525a9155e416ab9e4d8ad167e95f038f48d8f9e7 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Tue, 10 Jun 2025 21:00:16 +0200 Subject: [PATCH] fix(editor): moving and scaling models --- core/src/datatypes/cframe.h | 4 ++++ core/src/handles.cpp | 20 +++++++++----------- core/src/partassembly.cpp | 5 +++-- core/src/partassembly.h | 2 ++ core/src/rendering/renderer.cpp | 8 ++++---- editor/mainglwidget.cpp | 16 ++++++++-------- 6 files changed, 30 insertions(+), 25 deletions(-) diff --git a/core/src/datatypes/cframe.h b/core/src/datatypes/cframe.h index 8461380..a6d8eda 100644 --- a/core/src/datatypes/cframe.h +++ b/core/src/datatypes/cframe.h @@ -68,4 +68,8 @@ public: DEF_DATA_OP Vector3 operator *(Vector3) const; DEF_DATA_OP CFrame operator +(Vector3) const; DEF_DATA_OP CFrame operator -(Vector3) const; + + inline CFrame operator *=(CFrame otherFrame) { return *this = *this * otherFrame; } + inline CFrame operator +=(Vector3 offset) { return *this = *this + offset; } + inline CFrame operator -=(Vector3 offset) { return *this = *this - offset; } }; \ No newline at end of file diff --git a/core/src/handles.cpp b/core/src/handles.cpp index 1e28759..a35e37b 100644 --- a/core/src/handles.cpp +++ b/core/src/handles.cpp @@ -3,6 +3,7 @@ #include "datatypes/cframe.h" #include "datatypes/vector.h" #include "math_helper.h" +#include "partassembly.h" #include #include #include @@ -106,14 +107,13 @@ static std::shared_ptr getFirstSelectedPart() { } CFrame getLocalHandleCFrame(HandleFace face) { - glm::vec3 _boxPos, boxSize, _boxMin, _boxMax; - int count = getAABBOfSelection(_boxPos, boxSize, _boxMin, _boxMax); + PartAssembly assembly = PartAssembly::FromSelection(); Vector3 size; - if (count == 1 && !editorToolHandles.worldMode) - size = getFirstSelectedPart()->size; + if (editorToolHandles.worldMode) + size = assembly.bounds(); else - size = boxSize; + size = assembly.size(); // Since rotation displays rings, all handles must be the same distance from origin in order for the // rings to be circular @@ -125,12 +125,10 @@ CFrame getLocalHandleCFrame(HandleFace face) { } CFrame getHandleCFrame(HandleFace face) { - glm::vec3 boxPos, boxSize, _boxMin, _boxMax; - int count = getAABBOfSelection(boxPos, boxSize, _boxMin, _boxMax); + PartAssembly assembly = PartAssembly::FromSelection(); - if (count == 1 && !editorToolHandles.worldMode) { - auto part = getFirstSelectedPart(); - return part->cframe * getLocalHandleCFrame(face); + if (editorToolHandles.worldMode) { + return getLocalHandleCFrame(face) + assembly.assemblyOrigin().Position(); } else - return getLocalHandleCFrame(face) + boxPos; + return assembly.assemblyOrigin() * getLocalHandleCFrame(face); } \ No newline at end of file diff --git a/core/src/partassembly.cpp b/core/src/partassembly.cpp index 7c3e2c8..04e440e 100644 --- a/core/src/partassembly.cpp +++ b/core/src/partassembly.cpp @@ -14,7 +14,8 @@ PartAssembly::PartAssembly(std::vector> parts, bool worldM if (parts.size() == 0) return; if (parts.size() == 1 && !worldMode) { _assemblyOrigin = parts[0]->cframe; - _bounds = parts[0]->size; + _size = parts[0]->size; + _bounds = parts[0]->GetAABB(); return; } @@ -30,7 +31,7 @@ PartAssembly::PartAssembly(std::vector> parts, bool worldM getAABBCoords(pos, size, min, max); _assemblyOrigin = CFrame() + pos; - _bounds = size; + _size = _bounds = size; } PartAssembly PartAssembly::FromSelection(std::vector> newSelection) { diff --git a/core/src/partassembly.h b/core/src/partassembly.h index 75be536..5f899a7 100644 --- a/core/src/partassembly.h +++ b/core/src/partassembly.h @@ -12,6 +12,7 @@ const std::vector> getSelection(); class PartAssembly { CFrame _assemblyOrigin; Vector3 _bounds; + Vector3 _size; std::vector> parts; public: @@ -21,6 +22,7 @@ public: inline CFrame assemblyOrigin() { return _assemblyOrigin; }; inline Vector3 bounds() { return _bounds; }; + inline Vector3 size() { return _size; }; // Transforms the assembly such that newOrigin is now this assembly's new assemblyOrigin void SetOrigin(CFrame newOrigin); diff --git a/core/src/rendering/renderer.cpp b/core/src/rendering/renderer.cpp index c4ec5bc..c0561e9 100644 --- a/core/src/rendering/renderer.cpp +++ b/core/src/rendering/renderer.cpp @@ -271,7 +271,7 @@ void renderHandles() { if (!editorToolHandles.active) return; auto assembly = PartAssembly::FromSelection(); - if (assembly.bounds() == Vector3::ZERO) return; + if (assembly.size() == Vector3::ZERO) return; glDepthMask(GL_TRUE); glCullFace(GL_BACK); @@ -517,9 +517,9 @@ void renderSelectionAssembly() { outlineShader->set("color", glm::vec3(1.f, 0.f, 0.f)); glm::mat4 model = selectionAssembly.assemblyOrigin(); - model = glm::scale(model, (glm::vec3)selectionAssembly.bounds() + glm::vec3(0.1)); + model = glm::scale(model, (glm::vec3)selectionAssembly.size() + glm::vec3(0.1)); outlineShader->set("model", model); - outlineShader->set("scale", (glm::vec3)selectionAssembly.bounds() + glm::vec3(0.05)); + outlineShader->set("scale", (glm::vec3)selectionAssembly.size() + glm::vec3(0.05)); outlineShader->set("thickness", 0.2f); OUTLINE_MESH->bind(); @@ -563,7 +563,7 @@ void renderRotationArcs() { glm::mat4 model = assembly.assemblyOrigin() * CFrame(glm::vec3(0), face.normal, glm::vec3(0, 1.01, 0.1)); handleShader->set("model", model); - float radius = glm::max(assembly.bounds().X(), assembly.bounds().Y(), assembly.bounds().Z()) / 2.f + 2.f; + float radius = glm::max(assembly.size().X(), assembly.size().Y(), assembly.size().Z()) / 2.f + 2.f; handleShader->set("material", Material { .diffuse = glm::abs(face.normal), diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index 89d9564..f2b279c 100755 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -154,7 +154,7 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { localFrame = snapCFrame(localFrame); // Snap to studs - Vector3 draggingPartSize = initialAssembly.bounds(); + Vector3 draggingPartSize = initialAssembly.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 @@ -164,7 +164,7 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { // Unsink the object // Get the normal of the surface relative to the part's frame, and get the size along that vector - Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * initialAssembly.bounds() / 2); + Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * initialAssembly.size() / 2); initialAssembly.SetOrigin(newFrame + unsinkOffset); } @@ -180,7 +180,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) { QPoint position = evt->pos(); - auto part = getHandleAdornee(); + // auto part = getHandleAdornee(); // This was actually quite a difficult problem to solve, managing to get the handle to go underneath the cursor @@ -192,7 +192,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) { CFrame handleCFrame = getHandleCFrame(draggingHandle.value()) + dragStartHandleOffset; // Current frame. Identity frame if worldMode == true, selected object's frame if worldMode == false - CFrame frame = editorToolHandles.worldMode ? CFrame::IDENTITY + part->position() : part->cframe.Rotation(); + CFrame frame = editorToolHandles.worldMode ? CFrame::IDENTITY + initialAssembly.assemblyOrigin().Position() : initialAssembly.assemblyOrigin().Rotation(); // Segment from axis stretching -4096 to +4096 rel to handle's position glm::vec3 axisSegment0 = handleCFrame.Position() + (-handleCFrame.LookVector() * 4096.0f); @@ -224,17 +224,17 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) { } else if (editorToolHandles.handlesType == ScaleHandles) { if (evt->modifiers() & Qt::AltModifier) { // If size gets too small, don't - if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.bounds() + abs(draggingHandle->normal) * diff * 2.f), glm::vec3(0.001f)))) + if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.size() + abs(draggingHandle->normal) * diff * 2.f), glm::vec3(0.001f)))) return; - selectionAssembly.Scale(selectionAssembly.bounds() + abs(draggingHandle->normal) * diff * 2.f, diff > 0); + selectionAssembly.Scale(selectionAssembly.size() + abs(draggingHandle->normal) * diff * 2.f, diff > 0); } else { // If size gets too small, don't - if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.bounds() + abs(draggingHandle->normal) * diff), glm::vec3(0.001f)))) + if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.size() + abs(draggingHandle->normal) * diff), glm::vec3(0.001f)))) return; selectionAssembly.TransformBy(CFrame() + absDiff * 0.5f); - selectionAssembly.Scale(selectionAssembly.bounds() + abs(draggingHandle->normal) * diff, diff > 0); + selectionAssembly.Scale(selectionAssembly.size() + abs(draggingHandle->normal) * diff, diff > 0); } } }