mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 10:04:19 -05:00
renderer: implement window wobble (#14920)
Adds a new window transformer, and wobble framework.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
#include <helpers/DeformableMesh.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
TEST(Helpers, deformableMeshSetSizeClamps) {
|
||||
CDeformableMesh mesh;
|
||||
|
||||
mesh.setSize(1);
|
||||
EXPECT_EQ(mesh.size(), 2u);
|
||||
|
||||
mesh.setSize(64);
|
||||
EXPECT_EQ(mesh.size(), 32u);
|
||||
}
|
||||
|
||||
TEST(Helpers, deformableMeshNoopUpdateKeepsExtents) {
|
||||
CDeformableMesh mesh(4);
|
||||
CBox box = {10, 20, 100, 50};
|
||||
|
||||
mesh.onPositionUpdate(box, box, 1.F);
|
||||
|
||||
const auto EXTENTS = mesh.transformedExtents(box);
|
||||
EXPECT_DOUBLE_EQ(EXTENTS.x, box.x);
|
||||
EXPECT_DOUBLE_EQ(EXTENTS.y, box.y);
|
||||
EXPECT_DOUBLE_EQ(EXTENTS.w, box.w);
|
||||
EXPECT_DOUBLE_EQ(EXTENTS.h, box.h);
|
||||
EXPECT_TRUE(mesh.stable(0.F, 0.F));
|
||||
}
|
||||
|
||||
TEST(Helpers, deformableMeshPositionUpdateExpandsExtents) {
|
||||
CDeformableMesh mesh(4);
|
||||
|
||||
const CBox PREVIOUS = {0, 0, 100, 50};
|
||||
const CBox CURRENT = {10, 0, 100, 50};
|
||||
mesh.onPositionUpdate(PREVIOUS, CURRENT, 1.F);
|
||||
|
||||
const auto EXTENTS = mesh.transformedExtents(CURRENT);
|
||||
EXPECT_LT(EXTENTS.x, CURRENT.x);
|
||||
EXPECT_GE(EXTENTS.x + EXTENTS.w, CURRENT.x + CURRENT.w);
|
||||
EXPECT_FALSE(mesh.stable(0.F, 0.F));
|
||||
}
|
||||
|
||||
TEST(Helpers, deformableMeshGrabPointAnchorsNearestVertices) {
|
||||
CDeformableMesh mesh(3);
|
||||
|
||||
const CBox PREVIOUS = {0, 0, 100, 100};
|
||||
const CBox CURRENT = {0, 0, 100, 120};
|
||||
mesh.onPositionUpdate(PREVIOUS, CURRENT, 1.F, Vector2D{0.5, 0.0});
|
||||
|
||||
const auto VERTICES = mesh.verticesForBox(CURRENT, CURRENT, {100, 120});
|
||||
|
||||
const auto TOPCENTER = std::ranges::find_if(VERTICES, [](const auto& v) { return v.u == 0.5F && v.v == 0.F; });
|
||||
const auto CENTER = std::ranges::find_if(VERTICES, [](const auto& v) { return v.u == 0.5F && v.v == 0.5F; });
|
||||
|
||||
ASSERT_NE(TOPCENTER, VERTICES.end());
|
||||
ASSERT_NE(CENTER, VERTICES.end());
|
||||
EXPECT_LT(std::abs(TOPCENTER->y - TOPCENTER->v), std::abs(CENTER->y - CENTER->v));
|
||||
}
|
||||
|
||||
TEST(Helpers, deformableMeshPositionUpdateClampsDisplacement) {
|
||||
CDeformableMesh mesh(4);
|
||||
|
||||
const CBox PREVIOUS = {0, 0, 100, 50};
|
||||
const CBox CURRENT = {1000, 1000, 100, 50};
|
||||
mesh.onPositionUpdate(PREVIOUS, CURRENT, 2.F);
|
||||
|
||||
const auto EXTENTS = mesh.transformedExtents(CURRENT);
|
||||
EXPECT_GE(EXTENTS.x, CURRENT.x - 16.001);
|
||||
EXPECT_GE(EXTENTS.y, CURRENT.y - 16.001);
|
||||
EXPECT_LE(EXTENTS.x + EXTENTS.w, CURRENT.x + CURRENT.w + 16.001);
|
||||
EXPECT_LE(EXTENTS.y + EXTENTS.h, CURRENT.y + CURRENT.h + 16.001);
|
||||
}
|
||||
|
||||
TEST(Helpers, deformableMeshVerticesForBoxBuildsTriangles) {
|
||||
CDeformableMesh mesh(2);
|
||||
|
||||
const auto VERTICES = mesh.verticesForBox({0, 0, 100, 50}, {0, 0, 100, 50}, {100, 50});
|
||||
|
||||
ASSERT_EQ(VERTICES.size(), 6u);
|
||||
EXPECT_FLOAT_EQ(VERTICES.front().x, 0.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.front().y, 0.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.front().u, 0.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.front().v, 0.F);
|
||||
|
||||
EXPECT_FLOAT_EQ(VERTICES.back().x, 1.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.back().y, 1.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.back().u, 1.F);
|
||||
EXPECT_FLOAT_EQ(VERTICES.back().v, 1.F);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <render/transformer/TransformerList.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class CTestDamageTransformer : public Render::IWindowTransformer {
|
||||
public:
|
||||
CTestDamageTransformer(int priority, double scale, double add, bool active = true) : m_priority(priority), m_scale(scale), m_add(add), m_active(active) {
|
||||
;
|
||||
}
|
||||
|
||||
virtual SP<Render::IFramebuffer> transform(SP<Render::IFramebuffer> in, const Render::SWindowTransformContext& context) {
|
||||
(void)context;
|
||||
return in;
|
||||
}
|
||||
|
||||
virtual int priority() const {
|
||||
return m_priority;
|
||||
}
|
||||
|
||||
virtual bool active() const {
|
||||
return m_active;
|
||||
}
|
||||
|
||||
virtual CBox transformBoxForDamage(const CBox& currentBox) const {
|
||||
CBox box = currentBox;
|
||||
box.x = box.x * m_scale + m_add;
|
||||
box.w *= m_scale;
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_priority = 0;
|
||||
double m_scale = 1.0;
|
||||
double m_add = 0.0;
|
||||
bool m_active = true;
|
||||
};
|
||||
|
||||
TEST(Render, transformerListDamageBoxFollowsPriorityOrder) {
|
||||
Render::CWindowTransformerList list;
|
||||
list.emplace<CTestDamageTransformer>(20, 2.0, 0.0);
|
||||
list.emplace<CTestDamageTransformer>(10, 1.0, 3.0);
|
||||
|
||||
const CBox BOX = {1, 2, 10, 20};
|
||||
const auto OUT = list.transformBoxForDamage(BOX);
|
||||
|
||||
EXPECT_DOUBLE_EQ(OUT.x, 8.0);
|
||||
EXPECT_DOUBLE_EQ(OUT.y, 2.0);
|
||||
EXPECT_DOUBLE_EQ(OUT.w, 20.0);
|
||||
EXPECT_DOUBLE_EQ(OUT.h, 20.0);
|
||||
}
|
||||
|
||||
TEST(Render, transformerListDamageBoxSkipsInactiveTransformers) {
|
||||
Render::CWindowTransformerList list;
|
||||
list.emplace<CTestDamageTransformer>(10, 2.0, 0.0, false);
|
||||
list.emplace<CTestDamageTransformer>(20, 1.0, 3.0);
|
||||
|
||||
const CBox BOX = {1, 2, 10, 20};
|
||||
const auto OUT = list.transformBoxForDamage(BOX);
|
||||
|
||||
EXPECT_DOUBLE_EQ(OUT.x, 4.0);
|
||||
EXPECT_DOUBLE_EQ(OUT.w, 10.0);
|
||||
}
|
||||
Reference in New Issue
Block a user