feat(editor): multi-select rotation

This commit is contained in:
maelstrom 2025-05-31 01:53:28 +02:00
parent 80ec1a9132
commit e5c8bdd2e2
3 changed files with 14 additions and 12 deletions

View file

@ -1,6 +1,7 @@
#include "partassembly.h"
#include "common.h"
#include "datatypes/cframe.h"
#include "datatypes/meta.h"
#include "datatypes/vector.h"
#include "math_helper.h"
#include "objects/base/instance.h"
@ -48,6 +49,7 @@ void PartAssembly::SetOrigin(CFrame newOrigin) {
for (auto part : parts) {
part->cframe = newOrigin * (_assemblyOrigin.Inverse() * part->cframe);
part->UpdateProperty("CFrame");
// sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe));
}
_assemblyOrigin = newOrigin;
@ -57,6 +59,7 @@ void PartAssembly::TransformBy(CFrame transform) {
for (auto part : parts) {
part->cframe = transform * part->cframe;
part->UpdateProperty("CFrame");
sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe));
}
_assemblyOrigin = transform * _assemblyOrigin;
@ -66,6 +69,7 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
if (parts.size() == 1) {
parts[0]->size = newSize;
parts[0]->UpdateProperty("Size");
sendPropertyUpdatedSignal(parts[0], "Size", Data::Variant((Data::Vector3)parts[0]->size));
_bounds = newSize;
return;
}
@ -78,8 +82,10 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
localOff = localOff * factor;
part->cframe = part->cframe.Rotation() + _assemblyOrigin * localOff;
part->UpdateProperty("CFrame");
sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe));
part->size *= factor;
part->UpdateProperty("Size");
sendPropertyUpdatedSignal(part, "Size", Data::Variant((Data::Vector3)part->size));
}
_bounds = _bounds * factor;

View file

@ -556,16 +556,14 @@ void renderRotationArcs() {
// Pass in the camera position
handleShader->set("viewPos", camera.cameraPos);
// TODO: This won't do... Doesn't support rotating multiple objects, and expects the first selected item to be a part,
// which isn't always the case
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(getSelection()[0]);
PartAssembly assembly = PartAssembly::FromSelection();
for (HandleFace face : HandleFace::Faces) {
if (glm::any(glm::lessThan(face.normal, glm::vec3(0)))) continue;
glm::mat4 model = part->cframe * 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);
float radius = glm::max(part->size.x, part->size.y, part->size.z) / 2.f + 2.f;
float radius = glm::max(assembly.bounds().X(), assembly.bounds().Y(), assembly.bounds().Z()) / 2.f + 2.f;
handleShader->set("material", Material {
.diffuse = glm::abs(face.normal),

View file

@ -121,6 +121,7 @@ std::optional<HandleFace> draggingHandle;
Vector3 initialHitPos;
Vector3 initialHitNormal;
CFrame initialFrame;
PartAssembly initialAssembly({});
void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
if (!isMouseDragging || draggingObject.expired() || mainWindow()->selectedTool >= TOOL_SMOOTH) return;
@ -271,7 +272,6 @@ void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) {
if (!isMouseDragging || !draggingHandle || !editorToolHandles.active) return;
glm::vec2 destPoint = glm::vec2(evt->pos().x(), evt->pos().y());
auto part = getHandleAdornee();
// Calculate part pos as screen point
glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)width() / (float)height(), 0.1f, 1000.0f);
@ -303,11 +303,8 @@ void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) {
glm::vec3 angles = handleNormal * sign * glm::vec3(angle);
part->cframe = initialFrame * CFrame::FromEulerAnglesXYZ(-angles);
gWorkspace()->SyncPartPhysics(part);
part->UpdateProperty("Rotation");
sendPropertyUpdatedSignal(part, "Rotation", part->cframe.ToEulerAnglesXYZ());
CFrame newFrame = initialFrame * CFrame::FromEulerAnglesXYZ(-angles);
initialAssembly.SetOrigin(newFrame);
}
std::optional<HandleFace> MainGLWidget::raycastHandle(glm::vec3 pointDir) {
@ -375,7 +372,8 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
auto handle = raycastHandle(pointDir);
if (handle.has_value()) {
startPoint = glm::vec2(evt->pos().x(), evt->pos().y());
initialFrame = getHandleAdornee()->cframe;
initialAssembly = PartAssembly::FromSelection();
initialFrame = initialAssembly.assemblyOrigin();
isMouseDragging = true;
draggingHandle = handle;
startLinearTransform(evt);