core: Move to hyprutils for Math
Moves CRegion, CBox and Vector2D over to hyprutils. Requires hyprutils>=0.1.4
This commit is contained in:
parent
6e5804b53d
commit
fb15b7aa2a
76 changed files with 509 additions and 1004 deletions
|
|
@ -4,7 +4,7 @@
|
|||
#include <any>
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
#include "Vector2D.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../debug/Log.hpp"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <deque>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "Vector2D.hpp"
|
||||
#include "math/Math.hpp"
|
||||
|
||||
constexpr int BAKEDPOINTS = 255;
|
||||
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
|
||||
|
|
|
|||
|
|
@ -1,179 +0,0 @@
|
|||
#include "Box.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
wlr_box CBox::wlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return m_bWlrBox;
|
||||
}
|
||||
|
||||
wlr_box* CBox::pWlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return &m_bWlrBox;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(double scale) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(const Vector2D& scale) {
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
w *= scale.x;
|
||||
h *= scale.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::translate(const Vector2D& vec) {
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D CBox::middle() const {
|
||||
return Vector2D{x + w / 2.0, y + h / 2.0};
|
||||
}
|
||||
|
||||
bool CBox::containsPoint(const Vector2D& vec) const {
|
||||
return VECINRECT(vec, x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
bool CBox::empty() const {
|
||||
return w == 0 || h == 0;
|
||||
}
|
||||
|
||||
CBox& CBox::applyFromWlr() {
|
||||
x = m_bWlrBox.x;
|
||||
y = m_bWlrBox.y;
|
||||
w = m_bWlrBox.width;
|
||||
h = m_bWlrBox.height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::round() {
|
||||
float newW = x + w - std::round(x);
|
||||
float newH = y + h - std::round(y);
|
||||
x = std::round(x);
|
||||
y = std::round(y);
|
||||
w = std::round(newW);
|
||||
h = std::round(newH);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::transform(const wl_output_transform t, double w, double h) {
|
||||
wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h);
|
||||
applyFromWlr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::addExtents(const SWindowDecorationExtents& e) {
|
||||
x -= e.topLeft.x;
|
||||
y -= e.topLeft.y;
|
||||
w += e.topLeft.x + e.bottomRight.x;
|
||||
h += e.topLeft.y + e.bottomRight.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scaleFromCenter(double scale) {
|
||||
double oldW = w, oldH = h;
|
||||
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
x -= (w - oldW) / 2.0;
|
||||
y -= (h - oldH) / 2.0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::expand(const double& value) {
|
||||
x -= value;
|
||||
y -= value;
|
||||
w += value * 2.0;
|
||||
h += value * 2.0;
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
w = 0;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::noNegativeSize() {
|
||||
w = std::clamp(w, 0.0, std::numeric_limits<double>::infinity());
|
||||
h = std::clamp(h, 0.0, std::numeric_limits<double>::infinity());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox CBox::intersection(const CBox& other) const {
|
||||
const float newX = std::max(x, other.x);
|
||||
const float newY = std::max(y, other.y);
|
||||
const float newBottom = std::min(y + h, other.y + other.h);
|
||||
const float newRight = std::min(x + w, other.x + other.w);
|
||||
float newW = newRight - newX;
|
||||
float newH = newBottom - newY;
|
||||
|
||||
if (newW <= 0 || newH <= 0) {
|
||||
newW = 0;
|
||||
newH = 0;
|
||||
}
|
||||
|
||||
return {newX, newY, newW, newH};
|
||||
}
|
||||
|
||||
bool CBox::overlaps(const CBox& other) const {
|
||||
return (other.x + other.w >= x) && (x + w >= other.x) && (other.y + other.h >= y) && (y + h >= other.y);
|
||||
}
|
||||
|
||||
bool CBox::inside(const CBox& bound) const {
|
||||
return bound.x < x && bound.y < y && x + w < bound.x + bound.w && y + h < bound.y + bound.h;
|
||||
}
|
||||
|
||||
CBox CBox::roundInternal() {
|
||||
float newW = x + w - std::floor(x);
|
||||
float newH = y + h - std::floor(y);
|
||||
|
||||
return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)};
|
||||
}
|
||||
|
||||
CBox CBox::copy() const {
|
||||
return CBox{*this};
|
||||
}
|
||||
|
||||
Vector2D CBox::pos() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
Vector2D CBox::size() const {
|
||||
return {w, h};
|
||||
}
|
||||
|
||||
Vector2D CBox::closestPoint(const Vector2D& vec) const {
|
||||
if (containsPoint(vec))
|
||||
return vec;
|
||||
|
||||
Vector2D nv = vec;
|
||||
nv.x = std::clamp(nv.x, x, x + w);
|
||||
nv.y = std::clamp(nv.y, y, y + h);
|
||||
return nv;
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CBox::extentsFrom(const CBox& small) {
|
||||
return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}};
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Vector2D.hpp"
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../includes.hpp"
|
||||
|
||||
class CBox {
|
||||
public:
|
||||
CBox(double x_, double y_, double w_, double h_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
h = h_;
|
||||
}
|
||||
|
||||
CBox() {
|
||||
w = 0;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
CBox(const wlr_box& box) {
|
||||
x = box.x;
|
||||
y = box.y;
|
||||
w = box.width;
|
||||
h = box.height;
|
||||
}
|
||||
|
||||
CBox(const double d) {
|
||||
x = d;
|
||||
y = d;
|
||||
w = d;
|
||||
h = d;
|
||||
}
|
||||
|
||||
CBox(const Vector2D& pos, const Vector2D& size) {
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
w = size.x;
|
||||
h = size.y;
|
||||
}
|
||||
|
||||
wlr_box wlr();
|
||||
wlr_box* pWlr();
|
||||
|
||||
CBox& applyFromWlr();
|
||||
CBox& scale(double scale);
|
||||
CBox& scaleFromCenter(double scale);
|
||||
CBox& scale(const Vector2D& scale);
|
||||
CBox& translate(const Vector2D& vec);
|
||||
CBox& round();
|
||||
CBox& transform(const wl_output_transform t, double w, double h);
|
||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||
CBox& expand(const double& value);
|
||||
CBox& noNegativeSize();
|
||||
|
||||
CBox copy() const;
|
||||
CBox intersection(const CBox& other) const;
|
||||
bool overlaps(const CBox& other) const;
|
||||
bool inside(const CBox& bound) const;
|
||||
|
||||
SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box
|
||||
|
||||
Vector2D middle() const;
|
||||
Vector2D pos() const;
|
||||
Vector2D size() const;
|
||||
Vector2D closestPoint(const Vector2D& vec) const;
|
||||
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
|
||||
double x = 0, y = 0;
|
||||
union {
|
||||
double w;
|
||||
double width;
|
||||
};
|
||||
union {
|
||||
double h;
|
||||
double height;
|
||||
};
|
||||
|
||||
double rot = 0; /* rad, ccw */
|
||||
|
||||
//
|
||||
bool operator==(const CBox& rhs) const {
|
||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||
}
|
||||
|
||||
private:
|
||||
CBox roundInternal();
|
||||
|
||||
wlr_box m_bWlrBox;
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Vector2D.hpp"
|
||||
#include "math/Math.hpp"
|
||||
|
||||
typedef uint32_t DRMFormat;
|
||||
typedef uint32_t SHMFormat;
|
||||
|
|
|
|||
|
|
@ -762,7 +762,7 @@ Vector2D configStringToVector2D(const std::string& VALUE) {
|
|||
if (std::getline(iss, token))
|
||||
throw std::invalid_argument("Invalid string format");
|
||||
|
||||
return Vector2D(x, y);
|
||||
return Vector2D((double)x, (double)y);
|
||||
}
|
||||
|
||||
double normalizeAngleRad(double ang) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <string>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include "Vector2D.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include <vector>
|
||||
#include <format>
|
||||
|
||||
|
|
|
|||
|
|
@ -358,7 +358,9 @@ void CMonitor::addDamage(const CBox* box) {
|
|||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
if (wlr_damage_ring_add_box(&damage, const_cast<CBox*>(box)->pWlr()))
|
||||
wlr_box damageBox = {(int)box->x, (int)box->y, (int)box->w, (int)box->h};
|
||||
|
||||
if (wlr_damage_ring_add_box(&damage, &damageBox))
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <memory>
|
||||
#include <xf86drmMode.h>
|
||||
#include "Timer.hpp"
|
||||
#include "Region.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include <optional>
|
||||
#include "signal/Signal.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,183 +0,0 @@
|
|||
#include "Region.hpp"
|
||||
extern "C" {
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/region.h>
|
||||
}
|
||||
|
||||
constexpr const int64_t MAX_REGION_SIDE = 10000000;
|
||||
|
||||
CRegion::CRegion() {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
}
|
||||
|
||||
CRegion::CRegion(const pixman_region32_t* const ref) {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
pixman_region32_copy(&m_rRegion, ref);
|
||||
}
|
||||
|
||||
CRegion::CRegion(double x, double y, double w, double h) {
|
||||
pixman_region32_init_rect(&m_rRegion, x, y, w, h);
|
||||
}
|
||||
|
||||
CRegion::CRegion(wlr_box* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height);
|
||||
}
|
||||
|
||||
CRegion::CRegion(const CBox& box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h);
|
||||
}
|
||||
|
||||
CRegion::CRegion(pixman_box32_t* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
|
||||
}
|
||||
|
||||
CRegion::CRegion(const CRegion& other) {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
}
|
||||
|
||||
CRegion::CRegion(CRegion&& other) {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
pixman_region32_copy(&m_rRegion, other.pixman());
|
||||
}
|
||||
|
||||
CRegion::~CRegion() {
|
||||
pixman_region32_fini(&m_rRegion);
|
||||
}
|
||||
|
||||
CRegion& CRegion::clear() {
|
||||
pixman_region32_clear(&m_rRegion);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::set(const CRegion& other) {
|
||||
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::add(const CRegion& other) {
|
||||
pixman_region32_union(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::add(double x, double y, double w, double h) {
|
||||
pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::add(const CBox& other) {
|
||||
pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::subtract(const CRegion& other) {
|
||||
pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::intersect(const CRegion& other) {
|
||||
pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::intersect(double x, double y, double w, double h) {
|
||||
pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::invert(pixman_box32_t* box) {
|
||||
pixman_region32_inverse(&m_rRegion, &m_rRegion, box);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::invert(const CBox& box) {
|
||||
pixman_box32 pixmanBox = {box.x, box.y, box.w + box.x, box.h + box.y};
|
||||
return this->invert(&pixmanBox);
|
||||
}
|
||||
|
||||
CRegion& CRegion::translate(const Vector2D& vec) {
|
||||
pixman_region32_translate(&m_rRegion, vec.x, vec.y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::transform(const wl_output_transform t, double w, double h) {
|
||||
wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::rationalize() {
|
||||
intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2});
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion CRegion::copy() const {
|
||||
return CRegion(*this);
|
||||
}
|
||||
|
||||
CRegion& CRegion::scale(float scale) {
|
||||
wlr_region_scale(&m_rRegion, &m_rRegion, scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::scale(const Vector2D& scale) {
|
||||
wlr_region_scale_xy(&m_rRegion, &m_rRegion, scale.x, scale.y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<pixman_box32_t> CRegion::getRects() const {
|
||||
std::vector<pixman_box32_t> result;
|
||||
|
||||
int rectsNum = 0;
|
||||
const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum);
|
||||
|
||||
result.assign(RECTSARR, RECTSARR + rectsNum);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CBox CRegion::getExtents() {
|
||||
pixman_box32_t* box = pixman_region32_extents(&m_rRegion);
|
||||
return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1};
|
||||
}
|
||||
|
||||
bool CRegion::containsPoint(const Vector2D& vec) const {
|
||||
return pixman_region32_contains_point(&m_rRegion, vec.x, vec.y, nullptr);
|
||||
}
|
||||
|
||||
bool CRegion::empty() const {
|
||||
return !pixman_region32_not_empty(&m_rRegion);
|
||||
}
|
||||
|
||||
Vector2D CRegion::closestPoint(const Vector2D& vec) const {
|
||||
if (containsPoint(vec))
|
||||
return vec;
|
||||
|
||||
double bestDist = __FLT_MAX__;
|
||||
Vector2D leader = vec;
|
||||
|
||||
for (auto& box : getRects()) {
|
||||
double x = 0, y = 0;
|
||||
|
||||
if (vec.x >= box.x2)
|
||||
x = box.x2 - 1;
|
||||
else if (vec.x < box.x1)
|
||||
x = box.x1;
|
||||
else
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y >= box.y2)
|
||||
y = box.y2 - 1;
|
||||
else if (vec.y < box.y1)
|
||||
y = box.y1;
|
||||
else
|
||||
y = vec.y;
|
||||
|
||||
double distance = pow(x, 2) + pow(y, 2);
|
||||
if (distance < bestDist) {
|
||||
bestDist = distance;
|
||||
leader = {x, y};
|
||||
}
|
||||
}
|
||||
|
||||
return leader;
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#pragma once
|
||||
#include <pixman.h>
|
||||
#include <vector>
|
||||
#include "Vector2D.hpp"
|
||||
#include "Box.hpp"
|
||||
|
||||
struct wlr_box;
|
||||
|
||||
class CRegion {
|
||||
public:
|
||||
/* Create an empty region */
|
||||
CRegion();
|
||||
/* Create from a reference. Copies, does not own. */
|
||||
CRegion(const pixman_region32_t* const ref);
|
||||
/* Create from a box */
|
||||
CRegion(double x, double y, double w, double h);
|
||||
/* Create from a wlr_box */
|
||||
CRegion(wlr_box* box);
|
||||
/* Create from a CBox */
|
||||
CRegion(const CBox& box);
|
||||
/* Create from a pixman_box32_t */
|
||||
CRegion(pixman_box32_t* box);
|
||||
|
||||
CRegion(const CRegion&);
|
||||
CRegion(CRegion&&);
|
||||
|
||||
~CRegion();
|
||||
|
||||
CRegion& operator=(CRegion&& other) {
|
||||
pixman_region32_copy(&m_rRegion, other.pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& operator=(CRegion& other) {
|
||||
pixman_region32_copy(&m_rRegion, other.pixman());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& clear();
|
||||
CRegion& set(const CRegion& other);
|
||||
CRegion& add(const CRegion& other);
|
||||
CRegion& add(double x, double y, double w, double h);
|
||||
CRegion& add(const CBox& other);
|
||||
CRegion& subtract(const CRegion& other);
|
||||
CRegion& intersect(const CRegion& other);
|
||||
CRegion& intersect(double x, double y, double w, double h);
|
||||
CRegion& translate(const Vector2D& vec);
|
||||
CRegion& transform(const wl_output_transform t, double w, double h);
|
||||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CRegion& scale(const Vector2D& scale);
|
||||
CRegion& rationalize();
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
Vector2D closestPoint(const Vector2D& vec) const;
|
||||
CRegion copy() const;
|
||||
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
//
|
||||
pixman_region32_t* pixman() {
|
||||
return &m_rRegion;
|
||||
}
|
||||
|
||||
private:
|
||||
pixman_region32_t m_rRegion;
|
||||
};
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#include "Vector2D.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
Vector2D::Vector2D(double xx, double yy) {
|
||||
x = xx;
|
||||
y = yy;
|
||||
}
|
||||
|
||||
Vector2D::Vector2D() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
Vector2D::Vector2D(const Hyprlang::VEC2& ref) {
|
||||
x = ref.x;
|
||||
y = ref.y;
|
||||
}
|
||||
|
||||
Vector2D::~Vector2D() {}
|
||||
|
||||
double Vector2D::normalize() {
|
||||
// get max abs
|
||||
const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y);
|
||||
|
||||
x /= max;
|
||||
y /= max;
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
Vector2D Vector2D::floor() const {
|
||||
return Vector2D(std::floor(x), std::floor(y));
|
||||
}
|
||||
|
||||
Vector2D Vector2D::round() const {
|
||||
return Vector2D(std::round(x), std::round(y));
|
||||
}
|
||||
|
||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const {
|
||||
return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y));
|
||||
}
|
||||
|
||||
double Vector2D::distance(const Vector2D& other) const {
|
||||
return std::sqrt(distanceSq(other));
|
||||
}
|
||||
|
||||
double Vector2D::distanceSq(const Vector2D& other) const {
|
||||
return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y);
|
||||
}
|
||||
|
||||
double Vector2D::size() const {
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Vector2D Vector2D::getComponentMax(const Vector2D& other) const {
|
||||
return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y));
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <format>
|
||||
#include "../macros.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
class Vector2D {
|
||||
public:
|
||||
Vector2D(double, double);
|
||||
Vector2D();
|
||||
~Vector2D();
|
||||
Vector2D(const Hyprlang::VEC2&);
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
|
||||
// returns the scale
|
||||
double normalize();
|
||||
|
||||
Vector2D operator+(const Vector2D& a) const {
|
||||
return Vector2D(this->x + a.x, this->y + a.y);
|
||||
}
|
||||
Vector2D operator-(const Vector2D& a) const {
|
||||
return Vector2D(this->x - a.x, this->y - a.y);
|
||||
}
|
||||
Vector2D operator-() const {
|
||||
return Vector2D(-this->x, -this->y);
|
||||
}
|
||||
Vector2D operator*(const double& a) const {
|
||||
return Vector2D(this->x * a, this->y * a);
|
||||
}
|
||||
Vector2D operator/(const double& a) const {
|
||||
return Vector2D(this->x / a, this->y / a);
|
||||
}
|
||||
|
||||
bool operator==(const Vector2D& a) const {
|
||||
return a.x == x && a.y == y;
|
||||
}
|
||||
|
||||
bool operator!=(const Vector2D& a) const {
|
||||
return a.x != x || a.y != y;
|
||||
}
|
||||
|
||||
Vector2D operator*(const Vector2D& a) const {
|
||||
return Vector2D(this->x * a.x, this->y * a.y);
|
||||
}
|
||||
|
||||
Vector2D operator/(const Vector2D& a) const {
|
||||
return Vector2D(this->x / a.x, this->y / a.y);
|
||||
}
|
||||
|
||||
bool operator>(const Vector2D& a) const {
|
||||
return this->x > a.x && this->y > a.y;
|
||||
}
|
||||
|
||||
bool operator<(const Vector2D& a) const {
|
||||
return this->x < a.x && this->y < a.y;
|
||||
}
|
||||
Vector2D& operator+=(const Vector2D& a) {
|
||||
this->x += a.x;
|
||||
this->y += a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator-=(const Vector2D& a) {
|
||||
this->x -= a.x;
|
||||
this->y -= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator*=(const Vector2D& a) {
|
||||
this->x *= a.x;
|
||||
this->y *= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator/=(const Vector2D& a) {
|
||||
this->x /= a.x;
|
||||
this->y /= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator*=(const double& a) {
|
||||
this->x *= a;
|
||||
this->y *= a;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator/=(const double& a) {
|
||||
this->x /= a;
|
||||
this->y /= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double distance(const Vector2D& other) const;
|
||||
double distanceSq(const Vector2D& other) const;
|
||||
double size() const;
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const;
|
||||
|
||||
Vector2D floor() const;
|
||||
Vector2D round() const;
|
||||
|
||||
Vector2D getComponentMax(const Vector2D& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
format specification
|
||||
- 'j', as json array
|
||||
- 'X', same as std::format("{}x{}", vec.x, vec.y)
|
||||
- number, floating point precision, use `0` to format as integer
|
||||
*/
|
||||
template <typename CharT>
|
||||
struct std::formatter<Vector2D, CharT> : std::formatter<CharT> {
|
||||
bool formatJson = false;
|
||||
bool formatX = false;
|
||||
std::string precision = "";
|
||||
FORMAT_PARSE(FORMAT_FLAG('j', formatJson) //
|
||||
FORMAT_FLAG('X', formatX) //
|
||||
FORMAT_NUMBER(precision),
|
||||
Vector2D)
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Vector2D& vec, FormatContext& ctx) const {
|
||||
std::string formatString = precision.empty() ? "{}" : std::format("{{:.{}f}}", precision);
|
||||
|
||||
if (formatJson)
|
||||
formatString = std::format("[{0}, {0}]", formatString);
|
||||
else if (formatX)
|
||||
formatString = std::format("{0}x{0}", formatString);
|
||||
else
|
||||
formatString = std::format("[Vector2D: x: {0}, y: {0}]", formatString);
|
||||
try {
|
||||
string buf = std::vformat(formatString, std::make_format_args(vec.x, vec.y));
|
||||
return std::format_to(ctx.out(), "{}", buf);
|
||||
} catch (std::format_error& e) { return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y); }
|
||||
}
|
||||
};
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#include "AnimatedVariable.hpp"
|
||||
#include "../desktop/WLSurface.hpp"
|
||||
#include "signal/Signal.hpp"
|
||||
#include "Region.hpp"
|
||||
#include "math/Math.hpp"
|
||||
|
||||
class CMonitor;
|
||||
class IPointer;
|
||||
|
|
|
|||
220
src/helpers/math/Math.cpp
Normal file
220
src/helpers/math/Math.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
#include "Math.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) {
|
||||
switch (t) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL;
|
||||
case WL_OUTPUT_TRANSFORM_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_180;
|
||||
case WL_OUTPUT_TRANSFORM_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_90;
|
||||
case WL_OUTPUT_TRANSFORM_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_180;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_90;
|
||||
default: break;
|
||||
}
|
||||
return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL;
|
||||
}
|
||||
|
||||
static void matrixIdentity(float mat[9]) {
|
||||
static const float identity[9] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
memcpy(mat, identity, sizeof(identity));
|
||||
}
|
||||
|
||||
static void matrixMultiply(float mat[9], const float a[9], const float b[9]) {
|
||||
float product[9];
|
||||
|
||||
product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
|
||||
product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
|
||||
product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
|
||||
|
||||
product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6];
|
||||
product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7];
|
||||
product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8];
|
||||
|
||||
product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6];
|
||||
product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7];
|
||||
product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
|
||||
|
||||
memcpy(mat, product, sizeof(product));
|
||||
}
|
||||
|
||||
static void matrixTranspose(float mat[9], const float a[9]) {
|
||||
float transposition[9] = {
|
||||
a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8],
|
||||
};
|
||||
memcpy(mat, transposition, sizeof(transposition));
|
||||
}
|
||||
|
||||
static void matrixTranslate(float mat[9], float x, float y) {
|
||||
float translate[9] = {
|
||||
1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
wlr_matrix_multiply(mat, mat, translate);
|
||||
}
|
||||
|
||||
static void matrixScale(float mat[9], float x, float y) {
|
||||
float scale[9] = {
|
||||
x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
wlr_matrix_multiply(mat, mat, scale);
|
||||
}
|
||||
|
||||
static void matrixRotate(float mat[9], float rad) {
|
||||
float rotate[9] = {
|
||||
cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
wlr_matrix_multiply(mat, mat, rotate);
|
||||
}
|
||||
|
||||
static std::unordered_map<eTransform, std::array<float, 9>> transforms = {
|
||||
{HYPRUTILS_TRANSFORM_NORMAL,
|
||||
{
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_90,
|
||||
{
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_180,
|
||||
{
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_270,
|
||||
{
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED,
|
||||
{
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_90,
|
||||
{
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_180,
|
||||
{
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_270,
|
||||
{
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
}},
|
||||
};
|
||||
|
||||
static void matrixTransform(float mat[9], eTransform transform) {
|
||||
matrixMultiply(mat, mat, transforms.at(transform).data());
|
||||
}
|
||||
|
||||
static void matrixProjection(float mat[9], int width, int height, eTransform transform) {
|
||||
memset(mat, 0, sizeof(*mat) * 9);
|
||||
|
||||
const float* t = transforms.at(transform).data();
|
||||
float x = 2.0f / width;
|
||||
float y = 2.0f / height;
|
||||
|
||||
// Rotation + reflection
|
||||
mat[0] = x * t[0];
|
||||
mat[1] = x * t[1];
|
||||
mat[3] = y * -t[3];
|
||||
mat[4] = y * -t[4];
|
||||
|
||||
// Translation
|
||||
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
|
||||
|
||||
// Identity
|
||||
mat[8] = 1.0f;
|
||||
}
|
||||
|
||||
void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]) {
|
||||
double x = box.x;
|
||||
double y = box.y;
|
||||
double width = box.width;
|
||||
double height = box.height;
|
||||
|
||||
matrixIdentity(mat);
|
||||
matrixTranslate(mat, x, y);
|
||||
|
||||
if (rotation != 0) {
|
||||
matrixTranslate(mat, width / 2, height / 2);
|
||||
matrixRotate(mat, rotation);
|
||||
matrixTranslate(mat, -width / 2, -height / 2);
|
||||
}
|
||||
|
||||
wlr_matrix_scale(mat, width, height);
|
||||
|
||||
if (transform != HYPRUTILS_TRANSFORM_NORMAL) {
|
||||
matrixTranslate(mat, 0.5, 0.5);
|
||||
matrixTransform(mat, transform);
|
||||
matrixTranslate(mat, -0.5, -0.5);
|
||||
}
|
||||
|
||||
matrixMultiply(mat, projection, mat);
|
||||
}
|
||||
11
src/helpers/math/Math.hpp
Normal file
11
src/helpers/math/Math.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-server-protocol.h>
|
||||
|
||||
// includes box and vector as well
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
eTransform wlTransformToHyprutils(wl_output_transform t);
|
||||
void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue