Skip to content

Commit ccb9c5c

Browse files
committed
Allowing duplicate with alt and preserveAspectRatio with shift
1 parent 4a62840 commit ccb9c5c

7 files changed

Lines changed: 130 additions & 54 deletions

File tree

editor/render/SceneRender.cpp

Lines changed: 104 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,47 @@ void editor::SceneRender::mouseReleaseEvent(float x, float y){
695695
}
696696
}
697697

698-
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){
698+
Vector3 editor::SceneRender::getMatrixScale(const Matrix4& matrix){
699+
return Vector3(
700+
Vector3(matrix[0][0], matrix[0][1], matrix[0][2]).length(),
701+
Vector3(matrix[1][0], matrix[1][1], matrix[1][2]).length(),
702+
Vector3(matrix[2][0], matrix[2][1], matrix[2][2]).length());
703+
}
704+
705+
bool editor::SceneRender::isCorner2DGizmoSide(Gizmo2DSideSelected side){
706+
return side == Gizmo2DSideSelected::NX_NY || side == Gizmo2DSideSelected::NX_PY ||
707+
side == Gizmo2DSideSelected::PX_NY || side == Gizmo2DSideSelected::PX_PY;
708+
}
709+
710+
bool editor::SceneRender::gizmo2DSideUsesNegativeX(Gizmo2DSideSelected side){
711+
return side == Gizmo2DSideSelected::NX_NY || side == Gizmo2DSideSelected::NX_PY;
712+
}
713+
714+
bool editor::SceneRender::gizmo2DSideUsesNegativeY(Gizmo2DSideSelected side){
715+
return side == Gizmo2DSideSelected::NX_NY || side == Gizmo2DSideSelected::PX_NY;
716+
}
717+
718+
Vector2 editor::SceneRender::lockObject2DAspectRatio(const Vector2& startSize, const Vector2& candidateSize){
719+
if (startSize.x <= 0.0f || startSize.y <= 0.0f){
720+
return candidateSize;
721+
}
722+
723+
float scaleX = candidateSize.x / startSize.x;
724+
float scaleY = candidateSize.y / startSize.y;
725+
float chosenScale = (std::fabs(scaleX - 1.0f) >= std::fabs(scaleY - 1.0f)) ? scaleX : scaleY;
726+
727+
if (!std::isfinite(chosenScale)){
728+
return candidateSize;
729+
}
730+
731+
if (chosenScale < 0.0f){
732+
chosenScale = 0.0f;
733+
}
734+
735+
return Vector2(startSize.x * chosenScale, startSize.y * chosenScale);
736+
}
737+
738+
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, bool preserveAspectRatio){
699739
mouseRay = camera->screenToRay(x, y);
700740

701741
if (TerrainEditWindow* terrainEditWindow = Backend::getApp().getTerrainEditWindow()){
@@ -912,6 +952,14 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
912952
newTileH = tileStartHeight + localSizeDelta.y;
913953
}
914954

955+
if (preserveAspectRatio && isCorner2DGizmoSide(side)) {
956+
Vector2 lockedSize = lockObject2DAspectRatio(Vector2(tileStartWidth, tileStartHeight), Vector2(newTileW, newTileH));
957+
newTileW = lockedSize.x;
958+
newTileH = lockedSize.y;
959+
newTilePos.x = gizmo2DSideUsesNegativeX(side) ? (tileMaxX - newTileW) : tileStartPosition.x;
960+
newTilePos.y = gizmo2DSideUsesNegativeY(side) ? (tileMaxY - newTileH) : tileStartPosition.y;
961+
}
962+
915963
if (displaySettings.snapToGrid) {
916964
float spacing = displaySettings.gridSpacing2D;
917965
if (spacing > 0.0f) {
@@ -1005,12 +1053,61 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
10051053
bool isLayout = scene->getComponentArray<UILayoutComponent>()->hasEntity(entity);
10061054
bool isText = scene->getComponentArray<TextComponent>()->hasEntity(entity);
10071055

1008-
Vector3 newPos = gizmoRMatrix.inverse() * ((rretrun.point + cursorStartOffset) - gizmoStartPosition);
1056+
Gizmo2DSideSelected side = toolslayer.getGizmo2DSideSelected();
1057+
Vector3 deltaPos = gizmoRMatrix.inverse() * ((rretrun.point + cursorStartOffset) - gizmoStartPosition);
1058+
Vector3 deltaSize = gizmoRMatrix.inverse() * -(gizmoStartPosition - rretrun.point - cursorStartOffset);
1059+
1060+
Vector3 oScale = getMatrixScale(transform->modelMatrix);
1061+
if (oScale.x == 0.0f) oScale.x = 1.0f;
1062+
if (oScale.y == 0.0f) oScale.y = 1.0f;
1063+
Vector3 posOffset = Vector3::ZERO;
1064+
Vector2 sizeDeltaLocal = Vector2::ZERO;
1065+
1066+
if (side == Gizmo2DSideSelected::CENTER){
1067+
posOffset = deltaPos;
1068+
}else if (side == Gizmo2DSideSelected::NX){
1069+
posOffset.x = deltaPos.x;
1070+
sizeDeltaLocal.x = -deltaSize.x / oScale.x;
1071+
}else if (side == Gizmo2DSideSelected::NY){
1072+
posOffset.y = deltaPos.y;
1073+
sizeDeltaLocal.y = -deltaSize.y / oScale.y;
1074+
}else if (side == Gizmo2DSideSelected::PX){
1075+
sizeDeltaLocal.x = deltaSize.x / oScale.x;
1076+
}else if (side == Gizmo2DSideSelected::PY){
1077+
sizeDeltaLocal.y = deltaSize.y / oScale.y;
1078+
}else if (side == Gizmo2DSideSelected::NX_NY){
1079+
posOffset.x = deltaPos.x;
1080+
posOffset.y = deltaPos.y;
1081+
sizeDeltaLocal.x = -deltaSize.x / oScale.x;
1082+
sizeDeltaLocal.y = -deltaSize.y / oScale.y;
1083+
}else if (side == Gizmo2DSideSelected::NX_PY){
1084+
posOffset.x = deltaPos.x;
1085+
sizeDeltaLocal.x = -deltaSize.x / oScale.x;
1086+
sizeDeltaLocal.y = deltaSize.y / oScale.y;
1087+
}else if (side == Gizmo2DSideSelected::PX_NY){
1088+
posOffset.y = deltaPos.y;
1089+
sizeDeltaLocal.x = deltaSize.x / oScale.x;
1090+
sizeDeltaLocal.y = -deltaSize.y / oScale.y;
1091+
}else if (side == Gizmo2DSideSelected::PX_PY){
1092+
sizeDeltaLocal.x = deltaSize.x / oScale.x;
1093+
sizeDeltaLocal.y = deltaSize.y / oScale.y;
1094+
}
1095+
1096+
if (preserveAspectRatio && isCorner2DGizmoSide(side)){
1097+
Vector2 freeformSizeDeltaLocal = sizeDeltaLocal;
1098+
Vector2 lockedSize = lockObject2DAspectRatio(objectSizeOffset[entity], objectSizeOffset[entity] + sizeDeltaLocal);
1099+
sizeDeltaLocal = lockedSize - objectSizeOffset[entity];
1100+
if (gizmo2DSideUsesNegativeX(side)){
1101+
posOffset.x = (freeformSizeDeltaLocal.x != 0.0f) ? (posOffset.x * (sizeDeltaLocal.x / freeformSizeDeltaLocal.x)) : 0.0f;
1102+
}
1103+
if (gizmo2DSideUsesNegativeY(side)){
1104+
posOffset.y = (freeformSizeDeltaLocal.y != 0.0f) ? (posOffset.y * (sizeDeltaLocal.y / freeformSizeDeltaLocal.y)) : 0.0f;
1105+
}
1106+
}
10091107

1010-
Vector3 newSize = gizmoRMatrix.inverse() * -(gizmoStartPosition - rretrun.point - cursorStartOffset);
1108+
Vector3 newPos = gizmoStartPosition + (gizmoRMatrix * posOffset);
10111109

1012-
if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::CENTER){
1013-
newPos = gizmoStartPosition + (gizmoRMatrix * newPos);
1110+
if (side == Gizmo2DSideSelected::CENTER){
10141111
// Snap absolute world position to grid (must be done after newPos becomes world-space)
10151112
if (displaySettings.snapToGrid) {
10161113
float spacing = displaySettings.gridSpacing2D;
@@ -1019,31 +1116,6 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
10191116
newPos.y = std::round(newPos.y / spacing) * spacing;
10201117
}
10211118
}
1022-
newSize = Vector3(0, 0, 0);
1023-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::NX){
1024-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(newPos.x, 0, 0));
1025-
newSize = Vector3(-newSize.x, 0, 0);
1026-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::NY){
1027-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(0, newPos.y, 0));
1028-
newSize = Vector3(0, -newSize.y, 0);
1029-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::PX){
1030-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(0, 0, 0));
1031-
newSize = Vector3(newSize.x, 0, 0);
1032-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::PY){
1033-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(0, 0, 0));
1034-
newSize = Vector3(0, newSize.y, 0);
1035-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::NX_NY){
1036-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(newPos.x, newPos.y, 0));
1037-
newSize = Vector3(-newSize.x, -newSize.y, 0);
1038-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::NX_PY){
1039-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(newPos.x, 0, 0));
1040-
newSize = Vector3(-newSize.x, newSize.y, 0);
1041-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::PX_NY){
1042-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(0, newPos.y, 0));
1043-
newSize = Vector3(newSize.x, -newSize.y, 0);
1044-
}else if (toolslayer.getGizmo2DSideSelected() == Gizmo2DSideSelected::PX_PY){
1045-
newPos = gizmoStartPosition + (gizmoRMatrix * Vector3(0, 0, 0));
1046-
newSize = Vector3(newSize.x, newSize.y, 0);
10471119
}
10481120

10491121
Matrix4 gizmoMatrix = Matrix4::translateMatrix(newPos) * gizmoRMatrix * Matrix4::scaleMatrix(Vector3(1,1,1));
@@ -1053,12 +1125,7 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
10531125
objMatrix = transformParent->modelMatrix.inverse() * objMatrix;
10541126
}
10551127

1056-
Vector3 oScale = Vector3(1.0f, 1.0f, 1.0f);
1057-
oScale.x = Vector3(objMatrix[0][0], objMatrix[0][1], objMatrix[0][2]).length();
1058-
oScale.y = Vector3(objMatrix[1][0], objMatrix[1][1], objMatrix[1][2]).length();
1059-
oScale.z = Vector3(objMatrix[2][0], objMatrix[2][1], objMatrix[2][2]).length();
1060-
1061-
Vector2 size = objectSizeOffset[entity] + Vector2(newSize.x / oScale.x, newSize.y / oScale.y);
1128+
Vector2 size = objectSizeOffset[entity] + sizeDeltaLocal;
10621129
Vector3 pos = Vector3(objMatrix[3][0], objMatrix[3][1], objMatrix[3][2]);
10631130

10641131
if (size.x < 0) size.x = 0;
@@ -1077,13 +1144,12 @@ void editor::SceneRender::mouseDragEvent(float x, float y, float origX, float or
10771144
}
10781145
}
10791146

1080-
if (toolslayer.getGizmo2DSideSelected() != Gizmo2DSideSelected::NONE){
1147+
if (side != Gizmo2DSideSelected::NONE){
10811148
MultiPropertyCmd* multiCmd = new MultiPropertyCmd();
10821149
if (isLayout){
10831150
multiCmd->addPropertyCmd<unsigned int>(project, sceneProject->id, entity, ComponentType::UILayoutComponent, "width", static_cast<unsigned int>(size.x));
10841151
multiCmd->addPropertyCmd<unsigned int>(project, sceneProject->id, entity, ComponentType::UILayoutComponent, "height", static_cast<unsigned int>(size.y));
10851152
if (isText){
1086-
Gizmo2DSideSelected side = toolslayer.getGizmo2DSideSelected();
10871153
if (side == Gizmo2DSideSelected::NX || side == Gizmo2DSideSelected::PX ||
10881154
side == Gizmo2DSideSelected::NX_NY || side == Gizmo2DSideSelected::NX_PY ||
10891155
side == Gizmo2DSideSelected::PX_NY || side == Gizmo2DSideSelected::PX_PY) {

editor/render/SceneRender.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ namespace doriax::editor{
9393
OBB getFamilyOBB(Entity entity, float offset);
9494
void updateTerrainBrushCursor();
9595
float snapRotationAngle(float angle, bool invertRotationSnap) const;
96+
static Vector3 getMatrixScale(const Matrix4& matrix);
97+
static bool isCorner2DGizmoSide(Gizmo2DSideSelected side);
98+
static bool gizmo2DSideUsesNegativeX(Gizmo2DSideSelected side);
99+
static bool gizmo2DSideUsesNegativeY(Gizmo2DSideSelected side);
100+
static Vector2 lockObject2DAspectRatio(const Vector2& startSize, const Vector2& candidateSize);
96101

97102
protected:
98103
void updateCameraFrustum(CameraObjects& co, const CameraComponent& cameraComponent, bool isMainCamera, bool fixedSizeFrustum = true);
@@ -138,7 +143,7 @@ namespace doriax::editor{
138143
virtual void mouseHoverEvent(float x, float y);
139144
virtual void mouseClickEvent(float x, float y, std::vector<Entity> selEntities);
140145
virtual void mouseReleaseEvent(float x, float y);
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);
146+
virtual void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap, bool preserveAspectRatio);
142147

143148
virtual bool isAnyGizmoSideSelected() const;
144149
bool isTerrainEditing() const;

editor/render/SceneRender2D.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,8 +893,8 @@ void editor::SceneRender2D::mouseReleaseEvent(float x, float y){
893893
SceneRender::mouseReleaseEvent(x, y);
894894
}
895895

896-
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){
897-
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap);
896+
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, bool preserveAspectRatio){
897+
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap, preserveAspectRatio);
898898
}
899899

900900
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, bool invertRotationSnap) 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, bool preserveAspectRatio) 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
@@ -1795,8 +1795,8 @@ void editor::SceneRender3D::mouseReleaseEvent(float x, float y){
17951795
SceneRender::mouseReleaseEvent(x, y);
17961796
}
17971797

1798-
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){
1799-
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap);
1798+
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, bool preserveAspectRatio){
1799+
SceneRender::mouseDragEvent(x, y, origX, origY, project, sceneId, selEntities, disableSelection, invertRotationSnap, preserveAspectRatio);
18001800
}
18011801

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

editor/render/SceneRender3D.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ namespace doriax::editor{
9797
void mouseHoverEvent(float x, float y) override;
9898
void mouseClickEvent(float x, float y, std::vector<Entity> selEntities) override;
9999
void mouseReleaseEvent(float x, float y) override;
100-
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap) override;
100+
void mouseDragEvent(float x, float y, float origX, float origY, Project* project, size_t sceneId, std::vector<Entity> selEntities, bool disableSelection, bool invertRotationSnap, bool preserveAspectRatio) override;
101101

102102
ViewportGizmo* getViewportGizmo();
103103
};

0 commit comments

Comments
 (0)