feat: grid snapping wrt/ scaling and moving
This commit is contained in:
parent
32964df4c3
commit
4bfca68fb0
BIN
assets/icons/editor/snap05.png
Normal file
BIN
assets/icons/editor/snap05.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 868 B |
BIN
assets/icons/editor/snap1.png
Normal file
BIN
assets/icons/editor/snap1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 836 B |
BIN
assets/icons/editor/snapoff.png
Normal file
BIN
assets/icons/editor/snapoff.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 865 B |
|
@ -2,10 +2,12 @@
|
|||
#include <chrono>
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <glm/common.hpp>
|
||||
#include <glm/ext/matrix_projection.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <glm/geometric.hpp>
|
||||
#include <glm/gtc/round.hpp>
|
||||
#include <glm/matrix.hpp>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
@ -14,6 +16,7 @@
|
|||
|
||||
#include "datatypes/cframe.h"
|
||||
#include "editorcommon.h"
|
||||
#include "mainwindow.h"
|
||||
#include "objects/handles.h"
|
||||
#include "physics/util.h"
|
||||
#include "qcursor.h"
|
||||
|
@ -166,16 +169,28 @@ void MainGLWidget::handleHandleDrag(QMouseEvent* evt) {
|
|||
glm::vec3 handlePoint, rb;
|
||||
get_closest_points_between_segments(axisSegment0, axisSegment1, mouseSegment0, mouseSegment1, handlePoint, rb);
|
||||
|
||||
if (selectedTool == SelectedTool::MOVE)
|
||||
editorToolHandles->adornee->lock()->cframe = editorToolHandles->PartCFrameFromHandlePos(draggingHandle.value(), handlePoint);
|
||||
else if (selectedTool == SelectedTool::SCALE) {
|
||||
if (selectedTool == SelectedTool::MOVE) {
|
||||
glm::vec3 newPos = editorToolHandles->PartCFrameFromHandlePos(draggingHandle.value(), handlePoint).Position();
|
||||
glm::vec3 oldPos = editorToolHandles->adornee->lock()->cframe.Position();
|
||||
glm::vec3 diff = newPos - oldPos;
|
||||
|
||||
// Apply snapping
|
||||
if (snappingFactor()) diff = glm::floor(diff / snappingFactor()) * snappingFactor();
|
||||
newPos = diff + oldPos;
|
||||
|
||||
editorToolHandles->adornee->lock()->cframe = editorToolHandles->adornee->lock()->cframe.Rotation() + newPos;
|
||||
} else if (selectedTool == SelectedTool::SCALE) {
|
||||
glm::vec3 handlePos = editorToolHandles->PartCFrameFromHandlePos(draggingHandle.value(), handlePoint).Position();
|
||||
|
||||
// Find change in handles, and negate difference in sign between axes
|
||||
glm::vec3 diff = handlePos - glm::vec3(editorToolHandles->adornee->lock()->position());
|
||||
|
||||
// Apply snapping
|
||||
if (snappingFactor()) diff = glm::floor(diff / snappingFactor()) * snappingFactor();
|
||||
|
||||
editorToolHandles->adornee->lock()->size += diff * glm::sign(draggingHandle->normal);
|
||||
|
||||
// If alt is not pressed, also reposition the part such that only the dragged side gets lengthened
|
||||
// If ctrl is not pressed, also reposition the part such that only the dragged side gets lengthened
|
||||
if (!(evt->modifiers() & Qt::ControlModifier))
|
||||
editorToolHandles->adornee->lock()->cframe = editorToolHandles->adornee->lock()->cframe + (diff / 2.0f);
|
||||
}
|
||||
|
@ -297,4 +312,17 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) {
|
|||
void MainGLWidget::keyReleaseEvent(QKeyEvent* evt) {
|
||||
if (evt->key() == Qt::Key_W || evt->key() == Qt::Key_S) moveZ = 0;
|
||||
else if (evt->key() == Qt::Key_A || evt->key() == Qt::Key_D) moveX = 0;
|
||||
}
|
||||
|
||||
MainWindow* MainGLWidget::mainWindow() {
|
||||
return dynamic_cast<MainWindow*>(window());
|
||||
}
|
||||
|
||||
float MainGLWidget::snappingFactor() {
|
||||
switch (mainWindow()->snappingMode) {
|
||||
case GridSnappingMode::SNAP_1_STUD: return 1;
|
||||
case GridSnappingMode::SNAP_05_STUDS: return 0.5;
|
||||
case GridSnappingMode::SNAP_OFF: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef MAINGLWIDGET_H
|
||||
#define MAINGLWIDGET_H
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "objects/part.h"
|
||||
#include "qevent.h"
|
||||
#include <QOpenGLWidget>
|
||||
|
@ -31,6 +32,9 @@ protected:
|
|||
void mouseReleaseEvent(QMouseEvent* evt) override;
|
||||
void keyPressEvent(QKeyEvent* evt) override;
|
||||
void keyReleaseEvent(QKeyEvent* evt) override;
|
||||
|
||||
MainWindow* mainWindow();
|
||||
float snappingFactor();
|
||||
};
|
||||
|
||||
#endif // MAINGLWIDGET_H
|
||||
|
|
|
@ -40,11 +40,18 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
ConnectSelectionChangeHandler();
|
||||
|
||||
connect(ui->actionToolSelect, &QAction::triggered, this, [&]() { selectedTool = SelectedTool::SELECT; updateSelectedTool(); });
|
||||
connect(ui->actionToolMove, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::MOVE : SelectedTool::SELECT; updateSelectedTool(); });
|
||||
connect(ui->actionToolScale, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::SCALE : SelectedTool::SELECT; updateSelectedTool(); });
|
||||
connect(ui->actionToolRotate, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::ROTATE : SelectedTool::SELECT; updateSelectedTool(); });
|
||||
connect(ui->actionToolSelect, &QAction::triggered, this, [&]() { selectedTool = SelectedTool::SELECT; updateToolbars(); });
|
||||
connect(ui->actionToolMove, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::MOVE : SelectedTool::SELECT; updateToolbars(); });
|
||||
connect(ui->actionToolScale, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::SCALE : SelectedTool::SELECT; updateToolbars(); });
|
||||
connect(ui->actionToolRotate, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::ROTATE : SelectedTool::SELECT; updateToolbars(); });
|
||||
ui->actionToolSelect->setChecked(true);
|
||||
selectedTool = SelectedTool::SELECT;
|
||||
|
||||
connect(ui->actionGridSnap1, &QAction::triggered, this, [&]() { snappingMode = GridSnappingMode::SNAP_1_STUD; updateToolbars(); });
|
||||
connect(ui->actionGridSnap05, &QAction::triggered, this, [&]() { snappingMode = GridSnappingMode::SNAP_05_STUDS; updateToolbars(); });
|
||||
connect(ui->actionGridSnapOff, &QAction::triggered, this, [&]() { snappingMode = GridSnappingMode::SNAP_OFF; updateToolbars(); });
|
||||
ui->actionGridSnap1->setChecked(true);
|
||||
snappingMode = GridSnappingMode::SNAP_1_STUD;
|
||||
|
||||
connect(ui->actionToggleSimulation, &QAction::triggered, this, [&]() {
|
||||
simulationPlaying = !simulationPlaying;
|
||||
|
@ -80,7 +87,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
});
|
||||
|
||||
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
||||
updateSelectedTool();
|
||||
updateToolbars();
|
||||
});
|
||||
|
||||
// ui->explorerView->Init(ui);
|
||||
|
@ -134,12 +141,16 @@ void MainWindow::timerEvent(QTimerEvent* evt) {
|
|||
ui->mainWidget->updateCycle();
|
||||
}
|
||||
|
||||
void MainWindow::updateSelectedTool() {
|
||||
void MainWindow::updateToolbars() {
|
||||
ui->actionToolSelect->setChecked(selectedTool == SelectedTool::SELECT);
|
||||
ui->actionToolMove->setChecked(selectedTool == SelectedTool::MOVE);
|
||||
ui->actionToolScale->setChecked(selectedTool == SelectedTool::SCALE);
|
||||
ui->actionToolRotate->setChecked(selectedTool == SelectedTool::ROTATE);
|
||||
|
||||
ui->actionGridSnap1->setChecked(snappingMode == GridSnappingMode::SNAP_1_STUD);
|
||||
ui->actionGridSnap05->setChecked(snappingMode == GridSnappingMode::SNAP_05_STUDS);
|
||||
ui->actionGridSnapOff->setChecked(snappingMode == GridSnappingMode::SNAP_OFF);
|
||||
|
||||
if (selectedTool == SelectedTool::MOVE) editorToolHandles->worldMode = true;
|
||||
if (selectedTool == SelectedTool::SCALE) editorToolHandles->worldMode = false;
|
||||
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
#include <QMainWindow>
|
||||
#include <QLineEdit>
|
||||
|
||||
enum GridSnappingMode {
|
||||
SNAP_1_STUD,
|
||||
SNAP_05_STUDS,
|
||||
SNAP_OFF,
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
|
@ -22,11 +28,13 @@ public:
|
|||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
GridSnappingMode snappingMode;
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
private:
|
||||
QBasicTimer timer;
|
||||
|
||||
void updateSelectedTool();
|
||||
void updateToolbars();
|
||||
void timerEvent(QTimerEvent*) override;
|
||||
void ConnectSelectionChangeHandler();
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1027</width>
|
||||
<height>29</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
@ -115,6 +115,10 @@
|
|||
<addaction name="actionToolScale"/>
|
||||
<addaction name="actionToolRotate"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGridSnap1"/>
|
||||
<addaction name="actionGridSnap05"/>
|
||||
<addaction name="actionGridSnapOff"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionToggleSimulation"/>
|
||||
</widget>
|
||||
<action name="actionAddPart">
|
||||
|
@ -257,6 +261,60 @@
|
|||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridSnap1">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>assets/icons/editor/snap1.png</normaloff>assets/icons/editor/snap1.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1-Stud Snapping</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set grid snapping to 1 stud</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridSnap05">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>assets/icons/editor/snap05.png</normaloff>assets/icons/editor/snap05.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1/2-Stud Snapping</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set grid snapping to 1/2 studs</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridSnapOff">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>assets/icons/editor/snapoff.png</normaloff>assets/icons/editor/snapoff.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No Grid Snapping</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Turn grid snapping off</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
Loading…
Reference in a new issue