Skip to content

Commit 7915842

Browse files
committed
Implemented snap rotation
1 parent 335fc6f commit 7915842

10 files changed

Lines changed: 63 additions & 13 deletions

File tree

editor/Stream.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,8 @@ YAML::Node editor::Stream::encodeProject(Project* project) {
10761076
sceneNode["gridSpacing2D"] = sceneProject.displaySettings.gridSpacing2D;
10771077
sceneNode["gridSpacing3D"] = sceneProject.displaySettings.gridSpacing3D;
10781078
sceneNode["snapToGrid"] = sceneProject.displaySettings.snapToGrid;
1079+
sceneNode["snapRotation"] = sceneProject.displaySettings.snapRotation;
1080+
sceneNode["rotationSnapDegrees"] = sceneProject.displaySettings.rotationSnapDegrees;
10791081

10801082
if (sceneProject.sceneRender) {
10811083
Camera* editorCam = sceneProject.sceneRender->getCamera();
@@ -1223,6 +1225,8 @@ void editor::Stream::decodeProject(Project* project, const YAML::Node& node) {
12231225
if (sceneNode["gridSpacing2D"]) ds.gridSpacing2D = sceneNode["gridSpacing2D"].as<float>();
12241226
if (sceneNode["gridSpacing3D"]) ds.gridSpacing3D = sceneNode["gridSpacing3D"].as<float>();
12251227
if (sceneNode["snapToGrid"]) ds.snapToGrid = sceneNode["snapToGrid"].as<bool>();
1228+
if (sceneNode["snapRotation"]) ds.snapRotation = sceneNode["snapRotation"].as<bool>();
1229+
if (sceneNode["rotationSnapDegrees"]) ds.rotationSnapDegrees = sceneNode["rotationSnapDegrees"].as<float>();
12261230
}
12271231

12281232
if (sceneNode["editorCamera"]) {

editor/render/SceneRender.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ void editor::SceneRender::mouseReleaseEvent(float x, float y){
675675
}
676676
}
677677

678-
void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection){
678+
void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap){
679679
mouseRay = camera->screenToRay(x, y);
680680

681681
if (TerrainEditWindow* terrainEditWindow = Backend::getApp().getTerrainEditWindow()){
@@ -792,7 +792,7 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
792792
Vector3 cross = cursorStartOffset.crossProduct(lastPoint);
793793
float sign = cross.dotProduct(cursorPlane.normal);
794794

795-
float angle = (sign < 0) ? -orig_angle : orig_angle;
795+
float angle = snapRotationAngle((sign < 0) ? -orig_angle : orig_angle, invertRotationSnap);
796796

797797
Quaternion newRot = Quaternion(Angle::radToDefault(angle), rotationAxis) * rotationStartOffset;
798798

@@ -1107,6 +1107,20 @@ bool editor::SceneRender::isTerrainEditing() const{
11071107
return false;
11081108
}
11091109

1110+
float editor::SceneRender::snapRotationAngle(float angle, bool invertRotationSnap) const{
1111+
bool snapRotation = displaySettings.snapRotation;
1112+
if (invertRotationSnap){
1113+
snapRotation = !snapRotation;
1114+
}
1115+
1116+
if (!snapRotation || displaySettings.rotationSnapDegrees <= 0.0f){
1117+
return angle;
1118+
}
1119+
1120+
float snapStep = Angle::defaultToRad(displaySettings.rotationSnapDegrees);
1121+
return std::round(angle / snapStep) * snapStep;
1122+
}
1123+
11101124
void editor::SceneRender::updateTerrainBrushCursor(){
11111125
if (!terrainBrushLines){
11121126
return;

editor/render/SceneRender.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ namespace doriax::editor{
2424
float gridSpacing2D = 50.0f;
2525
float gridSpacing3D = 1.0f;
2626
bool snapToGrid = false;
27+
bool snapRotation = false;
28+
float rotationSnapDegrees = 15.0f;
2729
};
2830

2931
struct CameraObjects{
@@ -90,6 +92,7 @@ namespace doriax::editor{
9092
OBB getOBB(Entity entity, bool local);
9193
OBB getFamilyOBB(Entity entity, float offset);
9294
void updateTerrainBrushCursor();
95+
float snapRotationAngle(float angle, bool invertRotationSnap) const;
9396

9497
protected:
9598
void updateCameraFrustum(CameraObjects& co, const CameraComponent& cameraComponent, bool isMainCamera, bool fixedSizeFrustum = true);
@@ -135,7 +138,7 @@ namespace doriax::editor{
135138
virtual void mouseHoverEvent(float x, float y);
136139
virtual void mouseClickEvent(float x, float y, std::vector<Entity> selEntities);
137140
virtual void mouseReleaseEvent(float x, float y);
138-
virtual void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection);
141+
virtual void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap);
139142

140143
virtual bool isAnyGizmoSideSelected() const;
141144
bool isTerrainEditing() const;

editor/render/SceneRender2D.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,8 +842,8 @@ void editor::SceneRender2D::mouseReleaseEvent(float x, float y){
842842
SceneRender::mouseReleaseEvent(x, y);
843843
}
844844

845-
void editor::SceneRender2D::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection){
846-
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection);
845+
void editor::SceneRender2D::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap){
846+
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap);
847847
}
848848

849849
void editor::SceneRender2D::zoomAtPosition(float width, float height, Vector2 pos, float zoomFactor){

editor/render/SceneRender2D.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace doriax::editor{
4646
void mouseHoverEvent(float x, float y) override;
4747
void mouseClickEvent(float x, float y, std::vector<Entity> selEntities) override;
4848
void mouseReleaseEvent(float x, float y) override;
49-
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection) override;
49+
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap) override;
5050

5151
void zoomAtPosition(float width, float height, Vector2 pos, float zoomFactor);
5252

editor/render/SceneRender3D.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,8 +1337,8 @@ void editor::SceneRender3D::mouseReleaseEvent(float x, float y){
13371337
SceneRender::mouseReleaseEvent(x, y);
13381338
}
13391339

1340-
void editor::SceneRender3D::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection){
1341-
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection);
1340+
void editor::SceneRender3D::mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap){
1341+
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap);
13421342
}
13431343

13441344
editor::ViewportGizmo* editor::SceneRender3D::getViewportGizmo(){

editor/render/SceneRender3D.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ namespace doriax::editor{
7171
void mouseHoverEvent(float x, float y) override;
7272
void mouseClickEvent(float x, float y, std::vector<Entity> selEntities) override;
7373
void mouseReleaseEvent(float x, float y) override;
74-
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection) override;
74+
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap) override;
7575

7676
ViewportGizmo* getViewportGizmo();
7777
};

editor/window/Properties.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,14 +650,30 @@ std::string editor::Properties::replaceNumberedBrackets(const std::string& input
650650
return result;
651651
}
652652

653-
Vector3 editor::Properties::roundZero(const Vector3& val, const float threshold){
653+
Vector3 editor::Properties::roundZero(const Vector3& val, const float threshold) const{
654654
return Vector3(
655655
(fabs(val.x) < threshold) ? 0.0f : val.x,
656656
(fabs(val.y) < threshold) ? 0.0f : val.y,
657657
(fabs(val.z) < threshold) ? 0.0f : val.z
658658
);
659659
}
660660

661+
float editor::Properties::snapDisplayedAngle(float angle, float threshold) const{
662+
float rounded = std::round(angle);
663+
return (std::fabs(angle - rounded) <= threshold) ? rounded : angle;
664+
}
665+
666+
Vector3 editor::Properties::getDisplayedEulerAngles(const Quaternion& value, const RotationOrder& order, float zeroThreshold) const{
667+
constexpr float displaySnapThreshold = 0.05f;
668+
669+
Vector3 euler = roundZero(Quaternion(value).normalize().getEulerAngles(order), zeroThreshold);
670+
euler.x = snapDisplayedAngle(euler.x, displaySnapThreshold);
671+
euler.y = snapDisplayedAngle(euler.y, displaySnapThreshold);
672+
euler.z = snapDisplayedAngle(euler.z, displaySnapThreshold);
673+
674+
return euler;
675+
}
676+
661677
bool editor::Properties::compareVectorFloat(const float* a, const float* b, size_t elements, const float threshold){
662678
for (size_t i = 0; i < elements; ++i) {
663679
if (fabs(a[i] - b[i]) > threshold) {
@@ -2053,7 +2069,7 @@ bool editor::Properties::propertyRow(RowPropertyType type, ComponentType cpType,
20532069
PropertyData prop = Catalog::getProperty(sceneProject->scene, entity, cpType, id);
20542070
defArr = static_cast<float*>(prop.def);
20552071
qValue = *static_cast<Quaternion*>(prop.ref);
2056-
eValue[entity] = roundZero(Quaternion(qValue).normalize().getEulerAngles(order), zeroThreshold);
2072+
eValue[entity] = getDisplayedEulerAngles(qValue, order, zeroThreshold);
20572073
if (value){
20582074
if (std::fabs(value->x - eValue[entity].x) > compThreshold)
20592075
difX = true;

editor/window/Properties.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ namespace doriax::editor{
145145

146146
// replace [number] with []
147147
std::string replaceNumberedBrackets(const std::string& input);
148-
Vector3 roundZero(const Vector3& val, const float threshold);
148+
Vector3 roundZero(const Vector3& val, const float threshold) const;
149+
float snapDisplayedAngle(float angle, float threshold) const;
150+
Vector3 getDisplayedEulerAngles(const Quaternion& value, const RotationOrder& order, float zeroThreshold) const;
149151

150152
bool compareVectorFloat(const float* a, const float* b, size_t elements, const float threshold);
151153

editor/window/SceneWindow.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ void editor::SceneWindow::sceneEventHandler(SceneProject* sceneProject) {
703703
mouseLeftDraggedInside = true;
704704
}
705705
if (mouseLeftDraggedInside){
706-
sceneProject->sceneRender->mouseDragEvent(x, y, mouseLeftStartPos.x, mouseLeftStartPos.y, project, sceneId, project->getSelectedEntities(sceneId), disableSelection);
706+
sceneProject->sceneRender->mouseDragEvent(x, y, mouseLeftStartPos.x, mouseLeftStartPos.y, project, sceneId, project->getSelectedEntities(sceneId), disableSelection, io.KeyCtrl);
707707
}
708708
}
709709

@@ -1334,6 +1334,17 @@ void editor::SceneWindow::show() {
13341334
}
13351335
}
13361336

1337+
drawSettingRow(ICON_FA_ROTATE " Snap rotation", sceneProject.displaySettings.snapRotation);
1338+
1339+
ImGui::TableNextRow();
1340+
ImGui::TableSetColumnIndex(0);
1341+
ImGui::Text("%s", ICON_FA_ROTATE " Rotation step");
1342+
ImGui::TableSetColumnIndex(1);
1343+
if (!sceneProject.displaySettings.snapRotation) ImGui::BeginDisabled();
1344+
ImGui::SetNextItemWidth(-1);
1345+
ImGui::DragFloat("##RotationSnapDegrees", &sceneProject.displaySettings.rotationSnapDegrees, 1.0f, 0.1f, 180.0f, "%.1f");
1346+
if (!sceneProject.displaySettings.snapRotation) ImGui::EndDisabled();
1347+
13371348
ImGui::EndTable();
13381349
}
13391350

0 commit comments

Comments
 (0)