fix: blobs now allow to be drawn in device pixels to stay sharp
C++ / fmt (pull_request) Failing after 5s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 9s
JS/TS / lint (pull_request) Successful in 25s
Python / static (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 51s
Python / verify (pull_request) Failing after 1m25s
Rust / fmt (pull_request) Successful in 39s
Rust / clippy (pull_request) Successful in 59s
C++ / fmt (pull_request) Failing after 5s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 9s
JS/TS / lint (pull_request) Successful in 25s
Python / static (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 51s
Python / verify (pull_request) Failing after 1m25s
Rust / fmt (pull_request) Successful in 39s
Rust / clippy (pull_request) Successful in 59s
This commit is contained in:
@@ -7,19 +7,94 @@
|
||||
|
||||
namespace {
|
||||
constexpr float k_retireMs = 120.0f;
|
||||
}
|
||||
constexpr qint64 k_minEvalMs = 10;
|
||||
constexpr float k_staleSampleSec = 0.1f;
|
||||
constexpr float k_staleMovePx = 2.0f;
|
||||
constexpr float k_moveSpeed = 5.0f;
|
||||
constexpr float k_settleDelta = 0.004f;
|
||||
constexpr float k_settleVel = 0.05f;
|
||||
constexpr float k_identityEps = 0.0005f;
|
||||
constexpr float k_stillPx = 0.5f;
|
||||
constexpr int k_settleStillSamples = 3;
|
||||
} // namespace
|
||||
|
||||
BlobRect::BlobRect(QQuickItem* parent) : BlobShape(parent) {}
|
||||
BlobRect::BlobRect(QQuickItem* parent) : BlobShape(parent) {
|
||||
m_stillSamples = k_settleStillSamples;
|
||||
}
|
||||
|
||||
BlobRect::~BlobRect() {
|
||||
if (m_group) m_group->removeShape(this);
|
||||
}
|
||||
|
||||
bool BlobRect::needsFrame() const {
|
||||
return m_physicsActive || m_retiring ||
|
||||
m_stillSamples < k_settleStillSamples ||
|
||||
std::abs(m_dm00 - 1.0f) + std::abs(m_dm01) +
|
||||
std::abs(m_dm11 - 1.0f) >
|
||||
k_identityEps;
|
||||
}
|
||||
|
||||
void BlobRect::resetDeformMatrix() {
|
||||
m_dm00 = 1.0f;
|
||||
m_dm01 = 0.0f;
|
||||
m_dm11 = 1.0f;
|
||||
m_dmVel00 = m_dmVel01 = m_dmVel11 = 0.0f;
|
||||
m_retiring = false;
|
||||
m_physicsActive = false;
|
||||
BlobShape::resetDeformMatrix();
|
||||
}
|
||||
|
||||
void BlobRect::requestPhysics() {
|
||||
if (m_group) m_group->requestPhysics();
|
||||
}
|
||||
|
||||
void BlobRect::updatePolish() {
|
||||
BlobShape::updatePolish();
|
||||
|
||||
if (m_physicsActive || m_retiring) requestPhysics();
|
||||
}
|
||||
|
||||
void BlobRect::finishAtIdentity() {
|
||||
m_dm00 = 1.0f;
|
||||
m_dm01 = 0.0f;
|
||||
m_dm11 = 1.0f;
|
||||
m_deformMatrix = QMatrix4x4();
|
||||
m_retiring = false;
|
||||
m_physicsActive = false;
|
||||
emit rawDeformMatrixChanged();
|
||||
updateCenteredDeformMatrix();
|
||||
|
||||
if (m_group) m_group->markDirty();
|
||||
}
|
||||
|
||||
void BlobRect::beginRetire() {
|
||||
if (m_retiring) return;
|
||||
|
||||
m_retire00 = m_dm00;
|
||||
m_retire01 = m_dm01;
|
||||
m_retire11 = m_dm11;
|
||||
m_dmVel00 = m_dmVel01 = m_dmVel11 = 0.0f;
|
||||
m_retireElapsed.start();
|
||||
m_retiring = true;
|
||||
requestPhysics();
|
||||
}
|
||||
|
||||
void BlobRect::trySettle(float speed) {
|
||||
if (m_retiring) return;
|
||||
if (!m_physicsActive) return;
|
||||
|
||||
const float totalDelta =
|
||||
std::abs(m_dm00 - 1.0f) + std::abs(m_dm01) + std::abs(m_dm11 - 1.0f);
|
||||
const float totalVel =
|
||||
std::abs(m_dmVel00) + std::abs(m_dmVel01) + std::abs(m_dmVel11);
|
||||
|
||||
if (speed < k_moveSpeed && totalDelta < k_settleDelta &&
|
||||
totalVel < k_settleVel && m_stillSamples >= k_settleStillSamples) {
|
||||
beginRetire();
|
||||
}
|
||||
}
|
||||
|
||||
void BlobRect::updatePhysics() {
|
||||
if (m_retiring) {
|
||||
const float t = std::clamp(
|
||||
static_cast<float>(m_retireElapsed.elapsed()) / k_retireMs,
|
||||
@@ -28,100 +103,80 @@ void BlobRect::updatePolish() {
|
||||
const float s = t * t * (3.0f - 2.0f * t);
|
||||
|
||||
if (t >= 1.0f) {
|
||||
m_dm00 = 1.0f;
|
||||
m_dm01 = 0.0f;
|
||||
m_dm11 = 1.0f;
|
||||
m_deformMatrix = QMatrix4x4();
|
||||
m_retiring = false;
|
||||
m_physicsActive = false;
|
||||
} else {
|
||||
m_dm00 = m_retire00 + (1.0f - m_retire00) * s;
|
||||
m_dm01 = m_retire01 - m_retire01 * s;
|
||||
m_dm11 = m_retire11 + (1.0f - m_retire11) * s;
|
||||
m_deformMatrix = QMatrix4x4(
|
||||
m_dm00,
|
||||
m_dm01,
|
||||
0,
|
||||
0,
|
||||
m_dm01,
|
||||
m_dm11,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1);
|
||||
finishAtIdentity();
|
||||
return;
|
||||
}
|
||||
|
||||
m_dm00 = m_retire00 + (1.0f - m_retire00) * s;
|
||||
m_dm01 = m_retire01 - m_retire01 * s;
|
||||
m_dm11 = m_retire11 + (1.0f - m_retire11) * s;
|
||||
m_deformMatrix = QMatrix4x4(
|
||||
m_dm00, m_dm01, 0, 0, m_dm01, m_dm11, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
emit rawDeformMatrixChanged();
|
||||
updateCenteredDeformMatrix();
|
||||
|
||||
if (!m_physicsActive) return;
|
||||
} else {
|
||||
const float totalDelta = std::abs(m_dm00 - 1.0f) + std::abs(m_dm01) +
|
||||
std::abs(m_dm11 - 1.0f);
|
||||
const float totalVel =
|
||||
std::abs(m_dmVel00) + std::abs(m_dmVel01) + std::abs(m_dmVel11);
|
||||
|
||||
if (totalDelta < 0.004f && totalVel < 0.05f) beginRetire();
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this]() {
|
||||
if (m_physicsActive && m_group) m_group->markDirty();
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void BlobRect::beginRetire() {
|
||||
m_retire00 = m_dm00;
|
||||
m_retire01 = m_dm01;
|
||||
m_retire11 = m_dm11;
|
||||
m_dmVel00 = m_dmVel01 = m_dmVel11 = 0.0f;
|
||||
m_retireElapsed.start();
|
||||
m_retiring = true;
|
||||
}
|
||||
|
||||
void BlobRect::updatePhysics() {
|
||||
const QPointF scenePos = mapToScene(QPointF(width() / 2.0, height() / 2.0));
|
||||
|
||||
if (!m_physicsActive && !m_retiring) {
|
||||
const float stuck = std::abs(m_dm00 - 1.0f) + std::abs(m_dm01) +
|
||||
std::abs(m_dm11 - 1.0f);
|
||||
if (stuck > k_identityEps) {
|
||||
beginRetire();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_hasPrevPos) {
|
||||
m_prevScenePos = scenePos;
|
||||
m_elapsed.start();
|
||||
m_hasPrevPos = true;
|
||||
m_stillSamples = k_settleStillSamples;
|
||||
return;
|
||||
}
|
||||
|
||||
const float dt = static_cast<float>(m_elapsed.restart()) / 1000.0f;
|
||||
if (dt > 0.1f || dt < 0.001f) {
|
||||
m_prevScenePos = scenePos;
|
||||
if (m_physicsActive) checkAtRest(0.0f);
|
||||
const qint64 evalMs = m_elapsed.elapsed();
|
||||
if (evalMs < k_minEvalMs) {
|
||||
return;
|
||||
}
|
||||
m_elapsed.restart();
|
||||
|
||||
const float velX =
|
||||
static_cast<float>(scenePos.x() - m_prevScenePos.x()) / dt;
|
||||
const float velY =
|
||||
static_cast<float>(scenePos.y() - m_prevScenePos.y()) / dt;
|
||||
const float dx = static_cast<float>(scenePos.x() - m_prevScenePos.x());
|
||||
const float dy = static_cast<float>(scenePos.y() - m_prevScenePos.y());
|
||||
m_prevScenePos = scenePos;
|
||||
|
||||
if (std::abs(dx) + std::abs(dy) > k_stillPx)
|
||||
m_stillSamples = 0;
|
||||
else
|
||||
m_stillSamples += 1;
|
||||
|
||||
const float dt = static_cast<float>(evalMs) / 1000.0f;
|
||||
if (dt > k_staleSampleSec) {
|
||||
if (std::abs(dx) + std::abs(dy) > k_staleMovePx) {
|
||||
m_physicsActive = true;
|
||||
requestPhysics();
|
||||
} else {
|
||||
trySettle(0.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const float velX = dx / dt;
|
||||
const float velY = dy / dt;
|
||||
|
||||
const float speed = std::sqrt(velX * velX + velY * velY);
|
||||
|
||||
if (m_retiring) {
|
||||
if (speed > 5.0f)
|
||||
if (speed > k_moveSpeed)
|
||||
m_retiring = false;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_physicsActive) {
|
||||
if (speed < 5.0f) return;
|
||||
if (speed < k_moveSpeed) return;
|
||||
m_physicsActive = true;
|
||||
requestPhysics();
|
||||
}
|
||||
|
||||
const float kStretchFactor = static_cast<float>(m_deformScale);
|
||||
@@ -131,7 +186,7 @@ void BlobRect::updatePhysics() {
|
||||
float target01 = 0.0f;
|
||||
float target11 = 1.0f;
|
||||
|
||||
if (speed > 5.0f) {
|
||||
if (speed > k_moveSpeed) {
|
||||
const float targetStretch =
|
||||
1.0f + std::min(speed * kStretchFactor, kMaxStretch);
|
||||
const float targetCompress = 1.0f / targetStretch;
|
||||
@@ -165,7 +220,7 @@ void BlobRect::updatePhysics() {
|
||||
emit rawDeformMatrixChanged();
|
||||
updateCenteredDeformMatrix();
|
||||
|
||||
checkAtRest(speed);
|
||||
trySettle(speed);
|
||||
}
|
||||
|
||||
void BlobRect::setTopLeftRadius(qreal r) {
|
||||
@@ -340,16 +395,3 @@ void BlobRect::excludeCornersRemoveLast(QQmlListProperty<BlobRect>* prop) {
|
||||
if (self->m_group) self->m_group->markDirty();
|
||||
emit self->excludeCornersChanged();
|
||||
}
|
||||
|
||||
void BlobRect::checkAtRest(float speed) {
|
||||
if (m_retiring) return;
|
||||
|
||||
constexpr float kEpsilon = 0.002f;
|
||||
const bool atRest =
|
||||
std::abs(m_dm00 - 1.0f) < kEpsilon && std::abs(m_dm01) < kEpsilon &&
|
||||
std::abs(m_dm11 - 1.0f) < kEpsilon && std::abs(m_dmVel00) < kEpsilon &&
|
||||
std::abs(m_dmVel01) < kEpsilon && std::abs(m_dmVel11) < kEpsilon &&
|
||||
speed < 5.0f;
|
||||
|
||||
if (atRest) beginRetire();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user