disallow/undo rotation at low zooms and near world edge
This commit is contained in:
@@ -73,6 +73,8 @@ public:
|
||||
void resetZoom();
|
||||
void startScaling();
|
||||
void stopScaling();
|
||||
double getMinZoom();
|
||||
double getMaxZoom();
|
||||
|
||||
// Rotation
|
||||
void rotateBy(double sx, double sy, double ex, double ey, double duration = 0);
|
||||
@@ -82,6 +84,7 @@ public:
|
||||
void resetNorth();
|
||||
void startRotating();
|
||||
void stopRotating();
|
||||
bool canRotate();
|
||||
|
||||
// Debug
|
||||
void setDebug(bool value);
|
||||
|
||||
@@ -37,16 +37,19 @@ public:
|
||||
void setZoom(double zoom, time duration = 0);
|
||||
double getZoom() const;
|
||||
double getScale() const;
|
||||
void startRotating();
|
||||
void stopRotating();
|
||||
void startScaling();
|
||||
void stopScaling();
|
||||
double getMinZoom();
|
||||
double getMaxZoom();
|
||||
|
||||
// Angle
|
||||
void rotateBy(double sx, double sy, double ex, double ey, time duration = 0);
|
||||
void setAngle(double angle, time duration = 0);
|
||||
void setAngle(double angle, double cx, double cy);
|
||||
double getAngle() const;
|
||||
void startScaling();
|
||||
void stopScaling();
|
||||
void startRotating();
|
||||
void stopRotating();
|
||||
bool canRotate();
|
||||
|
||||
// Transitions
|
||||
bool needsTransition() const;
|
||||
@@ -63,7 +66,7 @@ private:
|
||||
void _moveBy(double dx, double dy, time duration = 0);
|
||||
void _setScale(double scale, double cx, double cy, time duration = 0);
|
||||
void _setScaleXY(double new_scale, double xn, double yn, time duration = 0);
|
||||
void _setAngle(double angle, time duration = 0);
|
||||
void _setAngle(double angle, time duration = 0, bool disable_interaction = false);
|
||||
void _clearPanning();
|
||||
void _clearRotating();
|
||||
void _clearScaling();
|
||||
@@ -93,6 +96,7 @@ private:
|
||||
std::shared_ptr<util::transition> scale_timeout;
|
||||
std::shared_ptr<util::transition> rotate_timeout;
|
||||
std::shared_ptr<util::transition> pan_timeout;
|
||||
std::shared_ptr<util::transition> interaction_timeout;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ public:
|
||||
// Changing
|
||||
bool isChanging() const;
|
||||
|
||||
// Interactive
|
||||
bool isInteractive() const;
|
||||
|
||||
private:
|
||||
double pixel_x() const;
|
||||
double pixel_y() const;
|
||||
@@ -57,6 +60,7 @@ private:
|
||||
bool rotating = false;
|
||||
bool scaling = false;
|
||||
bool panning = false;
|
||||
bool interactive = true;
|
||||
|
||||
// map position
|
||||
double x = 0, y = 0;
|
||||
|
||||
@@ -312,6 +312,14 @@ void Map::stopScaling() {
|
||||
update();
|
||||
}
|
||||
|
||||
double Map::getMinZoom() {
|
||||
return transform.getMinZoom();
|
||||
}
|
||||
|
||||
double Map::getMaxZoom() {
|
||||
return transform.getMaxZoom();
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Rotation
|
||||
|
||||
@@ -356,6 +364,10 @@ void Map::stopRotating() {
|
||||
update();
|
||||
}
|
||||
|
||||
bool Map::canRotate() {
|
||||
return transform.canRotate();
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Toggles
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
current.pixelRatio = final.pixelRatio = ratio;
|
||||
current.framebuffer[0] = final.framebuffer[0] = fb_w;
|
||||
current.framebuffer[1] = final.framebuffer[1] = fb_h;
|
||||
if (!canRotate()) _setAngle(0);
|
||||
constrain(current.scale, current.y);
|
||||
if (current.scale < MIN_ROTATE_SCALE && current.angle) _setAngle(0, 0);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -57,6 +57,12 @@ void Transform::_moveBy(const double dx, const double dy, const time duration) {
|
||||
|
||||
constrain(final.scale, final.y);
|
||||
|
||||
// Un-rotate when rotated and panning far enough to show off-world in corners.
|
||||
double w = final.scale * util::tileSize / 2;
|
||||
double m = std::sqrt(pow((current.width / 2), 2) + pow((current.height / 2), 2));
|
||||
double x = std::abs(sqrt(pow(final.x, 2) + pow(final.y, 2)));
|
||||
if (current.angle && w - x < m) _setAngle(0, 500_milliseconds, true);
|
||||
|
||||
if (duration == 0) {
|
||||
current.x = final.x;
|
||||
current.y = final.y;
|
||||
@@ -197,6 +203,18 @@ void Transform::stopScaling() {
|
||||
_clearScaling();
|
||||
}
|
||||
|
||||
double Transform::getMinZoom() {
|
||||
double test_scale = current.scale;
|
||||
double test_y = current.y;
|
||||
constrain(test_scale, test_y);
|
||||
|
||||
return std::log2(std::fmin(min_scale, test_scale));
|
||||
}
|
||||
|
||||
double Transform::getMaxZoom() {
|
||||
return std::log2(max_scale);
|
||||
}
|
||||
|
||||
void Transform::_clearScaling() {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
@@ -251,7 +269,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
constrain(final.scale, final.y);
|
||||
|
||||
// Undo rotation at low zooms.
|
||||
if (final.scale < MIN_ROTATE_SCALE && current.angle) _setAngle(0, 500_milliseconds);
|
||||
if (!canRotate() && current.angle) _setAngle(0, 500_milliseconds, true);
|
||||
|
||||
if (duration == 0) {
|
||||
current.scale = final.scale;
|
||||
@@ -344,7 +362,7 @@ void Transform::setAngle(const double new_angle, const double cx, const double c
|
||||
}
|
||||
}
|
||||
|
||||
void Transform::_setAngle(double new_angle, const time duration) {
|
||||
void Transform::_setAngle(double new_angle, const time duration, bool disable_interaction) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
while (new_angle > M_PI)
|
||||
@@ -355,14 +373,22 @@ void Transform::_setAngle(double new_angle, const time duration) {
|
||||
final.angle = new_angle;
|
||||
|
||||
// Prevent rotation at low zooms.
|
||||
if (final.scale < MIN_ROTATE_SCALE) final.angle = 0;
|
||||
if (!canRotate()) final.angle = 0;
|
||||
|
||||
if (duration == 0) {
|
||||
current.angle = final.angle;
|
||||
transitions.remove(interaction_timeout);
|
||||
current.interactive = true;
|
||||
} else {
|
||||
time start = util::now();
|
||||
transitions.emplace_front(std::make_shared<util::ease_transition<double>>(
|
||||
current.angle, final.angle, current.angle, start, duration));
|
||||
if (disable_interaction) {
|
||||
transitions.remove(interaction_timeout);
|
||||
current.interactive = false;
|
||||
interaction_timeout = std::make_shared<util::timeout<bool>>(true, current.interactive, start, duration);
|
||||
transitions.emplace_front(interaction_timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +426,10 @@ void Transform::_clearRotating() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Transform::canRotate() {
|
||||
return (current.scale >= MIN_ROTATE_SCALE);
|
||||
}
|
||||
|
||||
#pragma mark - Transition
|
||||
|
||||
bool Transform::needsTransition() const {
|
||||
|
||||
@@ -115,13 +115,20 @@ float TransformState::getAngle() const {
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Rotation
|
||||
#pragma mark - Changing
|
||||
|
||||
bool TransformState::isChanging() const {
|
||||
return rotating || scaling || panning;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Interactive
|
||||
|
||||
bool TransformState::isInteractive() const {
|
||||
return interactive;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - (private helper functions)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user