feat(editor): undoing movement/transformations

This commit is contained in:
maelstrom 2025-06-23 18:04:53 +02:00
parent cef5db5b2d
commit ed5aa597ad
3 changed files with 42 additions and 0 deletions

View file

@ -117,4 +117,18 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
}
_bounds = _bounds * factor;
}
std::vector<PartTransformState> PartAssembly::GetCurrentTransforms() {
std::vector<PartTransformState> transforms;
for (auto part : parts) {
PartTransformState t;
t.part = part;
t.cframe = part->cframe;
t.size = part->size;
transforms.push_back(t);
}
return transforms;
}

View file

@ -8,6 +8,12 @@ class Part;
class Instance;
class Selection;
struct PartTransformState {
std::shared_ptr<Part> part;
Vector3 size;
CFrame cframe;
};
class PartAssembly {
CFrame _assemblyOrigin;
Vector3 _bounds;
@ -25,6 +31,9 @@ public:
inline Vector3 size() { return _size; };
inline bool multipleSelected() { return parts.size() > 1; }
// Gets the current transform state of all the parts in the assembly
std::vector<PartTransformState> GetCurrentTransforms();
// Transforms the assembly such that newOrigin is now this assembly's new assemblyOrigin
void SetOrigin(CFrame newOrigin);

View file

@ -21,6 +21,7 @@
#include "rendering/renderer.h"
#include "rendering/shader.h"
#include "datatypes/variant.h"
#include "undohistory.h"
#define PI 3.14159
#define M_mainWindow dynamic_cast<MainWindow*>(window())
@ -120,6 +121,8 @@ CFrame snapCFrame(CFrame frame) {
return CFrame(frame.Position(), frame.Position() + closestVec1, closestVec2);
}
std::vector<PartTransformState> initialTransforms;
bool tryMouseContextMenu = false;
bool isMouseDragging = false;
std::weak_ptr<Part> draggingObject;
@ -359,6 +362,7 @@ void MainGLWidget::mouseMoveEvent(QMouseEvent* evt) {
}
void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
initialTransforms = {};
tryMouseContextMenu = evt->button() == Qt::RightButton;
switch(evt->button()) {
// Camera drag
@ -377,6 +381,8 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
startPoint = glm::vec2(evt->pos().x(), evt->pos().y());
initialAssembly = PartAssembly::FromSelection(gDataModel->GetService<Selection>());
initialFrame = initialAssembly.assemblyOrigin();
initialTransforms = PartAssembly::FromSelection(gDataModel->GetService<Selection>()).GetCurrentTransforms();
printf("%ld\n", initialTransforms.size());
isMouseDragging = true;
draggingHandle = handle;
startLinearTransform(evt);
@ -430,6 +436,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
//part.selected = true;
isMouseDragging = true;
draggingObject = part;
initialTransforms = PartAssembly::FromSelection({part}).GetCurrentTransforms();
if (evt->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)) {
auto sel = selection->Get();
if (std::find(sel.begin(), sel.end(), selObject) == sel.end())
@ -455,6 +462,17 @@ void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) {
draggingObject = {};
draggingHandle = std::nullopt;
if (!initialTransforms.empty()) {
UndoState historyState;
for (auto t : initialTransforms) {
historyState.push_back(UndoStatePropertyChanged { t.part, "CFrame", t.cframe, t.part->cframe });
historyState.push_back(UndoStatePropertyChanged { t.part, "Size", t.size, t.part->size });
}
M_mainWindow->undoManager.PushState(historyState);
}
// Open context menu
if (tryMouseContextMenu)
contextMenu.exec(QCursor::pos());
@ -505,6 +523,7 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) {
}));
gWorkspace()->SyncPartPhysics(lastPart);
lastPart->name = "Part" + std::to_string(partId++);
M_mainWindow->undoManager.PushState({ UndoStateInstanceCreated { lastPart, gWorkspace() } });
}
}