Transformations now commited step by step, fixes many transformation related bugs
This commit is contained in:
parent
b4babf978e
commit
a2e4a795f7
8 changed files with 127 additions and 47 deletions
|
|
@ -442,6 +442,8 @@ namespace FixedPoint {
|
|||
}
|
||||
|
||||
Multiplier operator*(const Multiplier& a) const {
|
||||
if(a.val == UnderlyingNumber(0))
|
||||
return Multiplier(0);
|
||||
return (*this) / Multiplier(a.val, !a.isReciprocal);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,3 +269,9 @@ template <typename T, int S> T transform_scalar(const Transform<T, 2, S>& transf
|
|||
template <typename T> std::array<Vector<T, 2>, 4> triangle_from_rect_points(const Vector<T, 2>& min, const Vector<T, 2>& max) {
|
||||
return {min, {min.x(), max.y()}, max, {max.x(), min.y()}};
|
||||
}
|
||||
|
||||
template <typename T> std::string vec_pretty(const Vector<T, 2>& a) {
|
||||
std::stringstream ss;
|
||||
ss << "[" << a.x() << ", " << a.y() << "]";
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue