Transformations now commited step by step, fixes many transformation related bugs

This commit is contained in:
Yousef Khadadeh 2025-08-04 18:14:28 +03:00
parent b4babf978e
commit a2e4a795f7
8 changed files with 127 additions and 47 deletions

View file

@ -72,6 +72,12 @@ void CoordSpaceHelper::scale_about_double(const WorldVec& scalePos, double scale
}
}
void CoordSpaceHelper::scale_about(const WorldVec& scalePos, const WorldMultiplier& scaleAmount) {
inverseScale = inverseScale / scaleAmount;
WorldVec mVec = pos - scalePos;
pos = scalePos + FixedPoint::multiplier_vec_div(mVec, scaleAmount);
}
void CoordSpaceHelper::scale_about(const WorldVec& scalePos, const WorldScalar& scaleAmount, bool flipScale) {
if(!flipScale) {
inverseScale /= scaleAmount;

View file

@ -85,6 +85,7 @@ class CoordSpaceHelper {
void scale(const WorldScalar& scaleAmount);
void rotate_about(const WorldVec& rotatePos, double angle);
void scale_about(const WorldVec& scalePos, const WorldScalar& scaleAmount, bool flipScale);
void scale_about(const WorldVec& scalePos, const WorldMultiplier& scaleAmount);
void scale_about_double(const WorldVec& scalePos, double scaleAmount);
void set_rotation(double newRotation);

View file

@ -1,35 +1,106 @@
#include "CoordSpaceHelperTransform.hpp"
#include "CoordSpaceHelper.hpp"
#include "nlohmann/json.hpp"
CoordSpaceHelperTransform::CoordSpaceHelperTransform() {}
CoordSpaceHelperTransform::CoordSpaceHelperTransform(const WorldVec& translationPos):
transformType(TransformType::TRANSLATE),
pos(translationPos)
{}
CoordSpaceHelperTransform::CoordSpaceHelperTransform(const WorldVec& rotatePos, double angle):
transformType(TransformType::ROTATE),
pos(rotatePos),
rotation(angle)
{}
CoordSpaceHelperTransform::CoordSpaceHelperTransform(const WorldVec& scalePos, const WorldMultiplier& inverseScaleAmount):
transformType(TransformType::SCALE),
pos(scalePos),
inverseScale(inverseScaleAmount)
{}
bool CoordSpaceHelperTransform::operator==(const CoordSpaceHelperTransform& otherCoords) const {
return rotation == otherCoords.rotation && pos == otherCoords.pos && inverseScale == otherCoords.inverseScale;
return otherCoords.transformType == transformType && rotation == otherCoords.rotation && pos == otherCoords.pos && inverseScale == otherCoords.inverseScale;
}
bool CoordSpaceHelperTransform::operator!=(const CoordSpaceHelperTransform& otherCoords) const {
return rotation != otherCoords.rotation || pos != otherCoords.pos || inverseScale != otherCoords.inverseScale;
}
WorldVec CoordSpaceHelperTransform::to_space_world(const WorldVec& coord) const {
return rotate_world_coord(FixedPoint::multiplier_vec_div((coord - pos), inverseScale), -rotation);
}
//WorldVec CoordSpaceHelperTransform::to_space_world(const WorldVec& coord) const {
// switch(transformType) {
// case TransformType::NONE:
// return coord;
// case TransformType::TRANSLATE:
// return (coord - pos);
// case TransformType::SCALE:
// return pos + FixedPoint::multiplier_vec_div(coord - pos, inverseScale);
// case TransformType::ROTATE:
// return rotate_world_coord(coord + pos, -rotation) - pos;
// }
// return coord;
//}
WorldVec CoordSpaceHelperTransform::from_space_world(const WorldVec& coord) const {
return FixedPoint::multiplier_vec_mult(rotate_world_coord(coord, rotation), inverseScale) + pos;
switch(transformType) {
case TransformType::NONE:
return coord;
case TransformType::TRANSLATE:
return (coord + pos);
case TransformType::SCALE:
return FixedPoint::multiplier_vec_div(coord - pos, inverseScale) + pos;
case TransformType::ROTATE:
return pos + rotate_world_coord(coord - pos, rotation);
}
return coord;
}
CoordSpaceHelper CoordSpaceHelperTransform::other_coord_space_to_this_space(const CoordSpaceHelper& other) const {
CoordSpaceHelper toRet;
toRet.pos = to_space_world(other.pos);
toRet.rotation = other.rotation - rotation;
toRet.inverseScale = other.inverseScale / inverseScale;
return toRet;
switch(transformType) {
case TransformType::NONE:
return other;
case TransformType::TRANSLATE: {
auto toRet = other;
toRet.translate(-pos);
return toRet;
}
case TransformType::SCALE: {
auto toRet = other;
toRet.scale_about(pos, WorldMultiplier(1) / inverseScale);
return toRet;
}
case TransformType::ROTATE: {
auto toRet = other;
toRet.rotate_about(pos, -rotation);
return toRet;
}
}
return other;
}
CoordSpaceHelper CoordSpaceHelperTransform::other_coord_space_from_this_space(const CoordSpaceHelper& other) const {
CoordSpaceHelper toRet;
toRet.pos = from_space_world(other.pos);
toRet.rotation = other.rotation + rotation;
toRet.inverseScale = other.inverseScale * inverseScale;
return toRet;
switch(transformType) {
case TransformType::NONE:
return other;
case TransformType::TRANSLATE: {
auto toRet = other;
toRet.translate(pos);
return toRet;
}
case TransformType::SCALE: {
auto toRet = other;
toRet.scale_about(pos, inverseScale);
return toRet;
}
case TransformType::ROTATE: {
auto toRet = other;
toRet.rotate_about(pos, rotation);
return toRet;
}
}
return other;
}
void CoordSpaceHelperTransform::translate(const WorldVec& translation) {
@ -55,15 +126,3 @@ void CoordSpaceHelperTransform::set_rotation(double newRotation) {
while (rotation < 0.0)
rotation += 2.0 * std::numbers::pi;
}
void CoordSpaceHelperTransform::scale_about(const WorldVec& scalePos, const WorldMultiplier& scaleAmount) {
inverseScale = inverseScale / scaleAmount;
WorldVec mVec = pos - scalePos;
pos = scalePos + FixedPoint::multiplier_vec_div(mVec, scaleAmount);
}
std::ostream& operator<<(std::ostream& os, const CoordSpaceHelperTransform& a) {
return os << "pos: [" << a.pos.x() << " " << a.pos.y() << "]\n"
<< "inverseScale: " << static_cast<WorldScalar>(a.inverseScale) << "\n"
<< "rotation: " << a.rotation << "\n";
}

View file

@ -15,8 +15,13 @@ struct DrawData;
class CoordSpaceHelperTransform {
public:
CoordSpaceHelperTransform();
CoordSpaceHelperTransform(const WorldVec& translationPos);
CoordSpaceHelperTransform(const WorldVec& rotatePos, double angle);
CoordSpaceHelperTransform(const WorldVec& scalePos, const WorldMultiplier& inverseScaleAmount);
WorldVec from_space_world(const WorldVec& coord) const;
WorldVec to_space_world(const WorldVec& coord) const;
//WorldVec to_space_world(const WorldVec& coord) const;
CoordSpaceHelper other_coord_space_to_this_space(const CoordSpaceHelper& other) const;
CoordSpaceHelper other_coord_space_from_this_space(const CoordSpaceHelper& other) const;
@ -24,12 +29,21 @@ class CoordSpaceHelperTransform {
bool operator==(const CoordSpaceHelperTransform& otherCoords) const;
bool operator!=(const CoordSpaceHelperTransform& otherCoords) const;
enum class TransformType {
NONE,
TRANSLATE,
ROTATE,
SCALE
};
private:
void set_rotation(double newRotation);
void translate(const WorldVec& translation);
void rotate_about(const WorldVec& rotatePos, double angle);
void scale_about(const WorldVec& scalePos, const WorldMultiplier& scaleAmount);
WorldVec pos{0, 0};
TransformType transformType = TransformType::NONE;
WorldVec pos{0, 0}; // rotation center, scale center, or translation value
WorldMultiplier inverseScale{1};
double rotation = 0.0;
};

View file

@ -231,8 +231,8 @@ void DrawingProgramSelection::update() {
selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right());
scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(initialSelectionAABB.max));
rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(rotateData.centerPos));
scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(initialSelectionAABB.max);
rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(rotateData.centerPos);
rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle);
rebuild_cam_space();
@ -243,19 +243,16 @@ void DrawingProgramSelection::update() {
if(mouse_collided_with_scale_point()) {
scaleData.currentPos = scaleData.startPos = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
scaleData.centerPos = selectionTransformCoords.from_space_world(initialSelectionAABB.center());
startingSelectionTransformCoords = selectionTransformCoords;
transformOpHappening = TransformOperation::SCALE;
}
else if(mouse_collided_with_rotate_center_handle_point())
transformOpHappening = TransformOperation::ROTATE_RELOCATE_CENTER;
else if(mouse_collided_with_rotate_handle_point()) {
rotateData.rotationAngle = 0.0;
startingSelectionTransformCoords = selectionTransformCoords;
transformOpHappening = TransformOperation::ROTATE;
}
else if(mouse_collided_with_selection_aabb()) {
translateData.startPos = drawP.world.get_mouse_world_pos();
startingSelectionTransformCoords = selectionTransformCoords;
transformOpHappening = TransformOperation::TRANSLATE;
}
else
@ -263,10 +260,8 @@ void DrawingProgramSelection::update() {
}
break;
case TransformOperation::TRANSLATE:
if(drawP.controls.leftClickHeld) {
selectionTransformCoords = startingSelectionTransformCoords;
selectionTransformCoords.translate(drawP.world.get_mouse_world_pos() - translateData.startPos);
}
if(drawP.controls.leftClickHeld)
selectionTransformCoords = CoordSpaceHelperTransform(drawP.world.get_mouse_world_pos() - translateData.startPos);
else {
commit_transform_selection();
return;
@ -288,8 +283,7 @@ void DrawingProgramSelection::update() {
if(!isAnyNumberZero) {
WorldMultiplier scaleAmount = WorldMultiplier(centerToScaleStartNorm) / WorldMultiplier(centerToScaleCurrentNorm);
selectionTransformCoords = startingSelectionTransformCoords;
selectionTransformCoords.scale_about(scaleData.centerPos, scaleAmount);
selectionTransformCoords = CoordSpaceHelperTransform(scaleData.centerPos, scaleAmount);
}
}
else {
@ -299,7 +293,7 @@ void DrawingProgramSelection::update() {
break;
case TransformOperation::ROTATE_RELOCATE_CENTER:
if(drawP.controls.leftClickHeld)
rotateData.centerPos = selectionTransformCoords.to_space_world(drawP.world.get_mouse_world_pos());
rotateData.centerPos = drawP.world.get_mouse_world_pos();
else
transformOpHappening = TransformOperation::NONE;
break;
@ -307,8 +301,7 @@ void DrawingProgramSelection::update() {
if(drawP.controls.leftClickHeld) {
Vector2f rotationPointDiff = drawP.world.main.input.mouse.pos - rotateData.centerHandlePoint;
rotateData.rotationAngle = std::atan2(rotationPointDiff.y(), rotationPointDiff.x());
selectionTransformCoords = startingSelectionTransformCoords;
selectionTransformCoords.rotate_about(selectionTransformCoords.from_space_world(rotateData.centerPos), rotateData.rotationAngle);
selectionTransformCoords = CoordSpaceHelperTransform(rotateData.centerPos, rotateData.rotationAngle);
}
else {
commit_transform_selection();
@ -321,9 +314,9 @@ void DrawingProgramSelection::update() {
deselect_all();
else if(drawP.world.main.input.key(InputManager::KEY_DRAW_DELETE).pressed)
delete_all();
else if(drawP.world.main.input.key(InputManager::KEY_COPY).pressed && startingSelectionTransformCoords == CoordSpaceHelperTransform())
else if(drawP.world.main.input.key(InputManager::KEY_COPY).pressed && selectionTransformCoords == CoordSpaceHelperTransform())
selection_to_clipboard();
else if(drawP.world.main.input.key(InputManager::KEY_CUT).pressed && startingSelectionTransformCoords == CoordSpaceHelperTransform()) {
else if(drawP.world.main.input.key(InputManager::KEY_CUT).pressed && selectionTransformCoords == CoordSpaceHelperTransform()) {
selection_to_clipboard();
delete_all();
}

View file

@ -44,6 +44,7 @@ class DrawingProgramSelection {
std::array<WorldVec, 4> selectionRectPoints;
CoordSpaceHelperTransform selectionTransformCoords;
std::unordered_set<CollabListType::ObjectInfoPtr> selectedSet;
DrawingProgramCache cache;
DrawingProgram& drawP;
@ -56,8 +57,6 @@ class DrawingProgramSelection {
ROTATE
} transformOpHappening = TransformOperation::NONE;
CoordSpaceHelperTransform startingSelectionTransformCoords;
struct TranslationData {
WorldVec startPos;
} translateData;