fix(editor): moving and scaling models
This commit is contained in:
parent
f93b33c012
commit
525a9155e4
6 changed files with 30 additions and 25 deletions
|
@ -68,4 +68,8 @@ public:
|
||||||
DEF_DATA_OP Vector3 operator *(Vector3) const;
|
DEF_DATA_OP Vector3 operator *(Vector3) const;
|
||||||
DEF_DATA_OP CFrame operator +(Vector3) const;
|
DEF_DATA_OP CFrame 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; }
|
||||||
};
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
#include "datatypes/cframe.h"
|
#include "datatypes/cframe.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "math_helper.h"
|
#include "math_helper.h"
|
||||||
|
#include "partassembly.h"
|
||||||
#include <glm/ext/scalar_common.hpp>
|
#include <glm/ext/scalar_common.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -106,14 +107,13 @@ static std::shared_ptr<Part> getFirstSelectedPart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrame getLocalHandleCFrame(HandleFace face) {
|
CFrame getLocalHandleCFrame(HandleFace face) {
|
||||||
glm::vec3 _boxPos, boxSize, _boxMin, _boxMax;
|
PartAssembly assembly = PartAssembly::FromSelection();
|
||||||
int count = getAABBOfSelection(_boxPos, boxSize, _boxMin, _boxMax);
|
|
||||||
|
|
||||||
Vector3 size;
|
Vector3 size;
|
||||||
if (count == 1 && !editorToolHandles.worldMode)
|
if (editorToolHandles.worldMode)
|
||||||
size = getFirstSelectedPart()->size;
|
size = assembly.bounds();
|
||||||
else
|
else
|
||||||
size = boxSize;
|
size = assembly.size();
|
||||||
|
|
||||||
// Since rotation displays rings, all handles must be the same distance from origin in order for the
|
// Since rotation displays rings, all handles must be the same distance from origin in order for the
|
||||||
// rings to be circular
|
// rings to be circular
|
||||||
|
@ -125,12 +125,10 @@ CFrame getLocalHandleCFrame(HandleFace face) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrame getHandleCFrame(HandleFace face) {
|
CFrame getHandleCFrame(HandleFace face) {
|
||||||
glm::vec3 boxPos, boxSize, _boxMin, _boxMax;
|
PartAssembly assembly = PartAssembly::FromSelection();
|
||||||
int count = getAABBOfSelection(boxPos, boxSize, _boxMin, _boxMax);
|
|
||||||
|
|
||||||
if (count == 1 && !editorToolHandles.worldMode) {
|
if (editorToolHandles.worldMode) {
|
||||||
auto part = getFirstSelectedPart();
|
return getLocalHandleCFrame(face) + assembly.assemblyOrigin().Position();
|
||||||
return part->cframe * getLocalHandleCFrame(face);
|
|
||||||
} else
|
} else
|
||||||
return getLocalHandleCFrame(face) + boxPos;
|
return assembly.assemblyOrigin() * getLocalHandleCFrame(face);
|
||||||
}
|
}
|
|
@ -14,7 +14,8 @@ PartAssembly::PartAssembly(std::vector<std::shared_ptr<Part>> parts, bool worldM
|
||||||
if (parts.size() == 0) return;
|
if (parts.size() == 0) return;
|
||||||
if (parts.size() == 1 && !worldMode) {
|
if (parts.size() == 1 && !worldMode) {
|
||||||
_assemblyOrigin = parts[0]->cframe;
|
_assemblyOrigin = parts[0]->cframe;
|
||||||
_bounds = parts[0]->size;
|
_size = parts[0]->size;
|
||||||
|
_bounds = parts[0]->GetAABB();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ PartAssembly::PartAssembly(std::vector<std::shared_ptr<Part>> parts, bool worldM
|
||||||
getAABBCoords(pos, size, min, max);
|
getAABBCoords(pos, size, min, max);
|
||||||
|
|
||||||
_assemblyOrigin = CFrame() + pos;
|
_assemblyOrigin = CFrame() + pos;
|
||||||
_bounds = size;
|
_size = _bounds = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartAssembly PartAssembly::FromSelection(std::vector<std::shared_ptr<Instance>> newSelection) {
|
PartAssembly PartAssembly::FromSelection(std::vector<std::shared_ptr<Instance>> newSelection) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ const std::vector<std::shared_ptr<Instance>> getSelection();
|
||||||
class PartAssembly {
|
class PartAssembly {
|
||||||
CFrame _assemblyOrigin;
|
CFrame _assemblyOrigin;
|
||||||
Vector3 _bounds;
|
Vector3 _bounds;
|
||||||
|
Vector3 _size;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Part>> parts;
|
std::vector<std::shared_ptr<Part>> parts;
|
||||||
public:
|
public:
|
||||||
|
@ -21,6 +22,7 @@ public:
|
||||||
|
|
||||||
inline CFrame assemblyOrigin() { return _assemblyOrigin; };
|
inline CFrame assemblyOrigin() { return _assemblyOrigin; };
|
||||||
inline Vector3 bounds() { return _bounds; };
|
inline Vector3 bounds() { return _bounds; };
|
||||||
|
inline Vector3 size() { return _size; };
|
||||||
|
|
||||||
// Transforms the assembly such that newOrigin is now this assembly's new assemblyOrigin
|
// Transforms the assembly such that newOrigin is now this assembly's new assemblyOrigin
|
||||||
void SetOrigin(CFrame newOrigin);
|
void SetOrigin(CFrame newOrigin);
|
||||||
|
|
|
@ -271,7 +271,7 @@ void renderHandles() {
|
||||||
if (!editorToolHandles.active) return;
|
if (!editorToolHandles.active) return;
|
||||||
|
|
||||||
auto assembly = PartAssembly::FromSelection();
|
auto assembly = PartAssembly::FromSelection();
|
||||||
if (assembly.bounds() == Vector3::ZERO) return;
|
if (assembly.size() == Vector3::ZERO) return;
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
|
@ -517,9 +517,9 @@ void renderSelectionAssembly() {
|
||||||
outlineShader->set("color", glm::vec3(1.f, 0.f, 0.f));
|
outlineShader->set("color", glm::vec3(1.f, 0.f, 0.f));
|
||||||
|
|
||||||
glm::mat4 model = selectionAssembly.assemblyOrigin();
|
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("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);
|
outlineShader->set("thickness", 0.2f);
|
||||||
|
|
||||||
OUTLINE_MESH->bind();
|
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));
|
glm::mat4 model = assembly.assemblyOrigin() * 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(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 {
|
handleShader->set("material", Material {
|
||||||
.diffuse = glm::abs(face.normal),
|
.diffuse = glm::abs(face.normal),
|
||||||
|
|
|
@ -154,7 +154,7 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
||||||
localFrame = snapCFrame(localFrame);
|
localFrame = snapCFrame(localFrame);
|
||||||
|
|
||||||
// Snap to studs
|
// Snap to studs
|
||||||
Vector3 draggingPartSize = initialAssembly.bounds();
|
Vector3 draggingPartSize = initialAssembly.size();
|
||||||
glm::vec3 inverseNormalPartSize = (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
|
||||||
|
@ -164,7 +164,7 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
||||||
|
|
||||||
// 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
|
||||||
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);
|
initialAssembly.SetOrigin(newFrame + unsinkOffset);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
||||||
|
|
||||||
QPoint position = evt->pos();
|
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
|
// 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;
|
CFrame handleCFrame = getHandleCFrame(draggingHandle.value()) + dragStartHandleOffset;
|
||||||
|
|
||||||
// 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
|
||||||
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
|
// 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);
|
||||||
|
@ -224,17 +224,17 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
||||||
} else if (editorToolHandles.handlesType == ScaleHandles) {
|
} else if (editorToolHandles.handlesType == ScaleHandles) {
|
||||||
if (evt->modifiers() & Qt::AltModifier) {
|
if (evt->modifiers() & Qt::AltModifier) {
|
||||||
// If size gets too small, don't
|
// 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;
|
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 {
|
} else {
|
||||||
// If size gets too small, don't
|
// 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;
|
return;
|
||||||
|
|
||||||
selectionAssembly.TransformBy(CFrame() + absDiff * 0.5f);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue