mirror of
https://git.allpurposem.at/mat/WiggleWobble.git
synced 2025-12-23 13:01:28 +01:00
chore: refactor to multiple files
This commit is contained in:
parent
28fd76c147
commit
8211583606
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define WLR_USE_UNSTABLE
|
|
||||||
|
|
||||||
#include <hyprland/src/render/decorations/IHyprWindowDecoration.hpp>
|
|
||||||
|
|
||||||
class CCustomDecoration : public IHyprWindowDecoration {
|
|
||||||
public:
|
|
||||||
CCustomDecoration(CWindow*);
|
|
||||||
virtual ~CCustomDecoration();
|
|
||||||
|
|
||||||
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
|
||||||
|
|
||||||
virtual void draw(CMonitor*, float a, const Vector2D& offset);
|
|
||||||
|
|
||||||
virtual eDecorationType getDecorationType();
|
|
||||||
|
|
||||||
virtual void updateWindow(CWindow*);
|
|
||||||
|
|
||||||
virtual void damageEntire();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SWindowDecorationExtents m_seExtents;
|
|
||||||
|
|
||||||
CWindow* m_pWindow = nullptr;
|
|
||||||
|
|
||||||
Vector2D m_vLastWindowPos;
|
|
||||||
Vector2D m_vLastWindowSize;
|
|
||||||
};
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define WLR_USE_UNSTABLE
|
|
||||||
|
|
||||||
#include <hyprland/src/layout/IHyprLayout.hpp>
|
|
||||||
|
|
||||||
struct SWindowData {
|
|
||||||
CWindow* pWindow = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CHyprCustomLayout : public IHyprLayout {
|
|
||||||
public:
|
|
||||||
virtual void onWindowCreatedTiling(CWindow*);
|
|
||||||
virtual void onWindowRemovedTiling(CWindow*);
|
|
||||||
virtual bool isWindowTiled(CWindow*);
|
|
||||||
virtual void recalculateMonitor(const int&);
|
|
||||||
virtual void recalculateWindow(CWindow*);
|
|
||||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
|
||||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
|
||||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
|
||||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
|
||||||
virtual void switchWindows(CWindow*, CWindow*);
|
|
||||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
|
||||||
virtual std::string getLayoutName();
|
|
||||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
|
||||||
|
|
||||||
virtual void onEnable();
|
|
||||||
virtual void onDisable();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<SWindowData> m_vWindowData;
|
|
||||||
};
|
|
||||||
17
include/globals.h
Normal file
17
include/globals.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef WW_GLOBALS_H
|
||||||
|
#define WW_GLOBALS_H
|
||||||
|
|
||||||
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||||
|
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||||
|
#include <hyprland/src/render/Framebuffer.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
inline HANDLE PHANDLE = nullptr;
|
||||||
|
|
||||||
|
class CWobblyWindow;
|
||||||
|
|
||||||
|
extern std::map<PHLWINDOWREF, CFramebuffer> g_windowFramebuffers;
|
||||||
|
extern std::map<PHLWINDOWREF, Vector2D> g_windowPositions;
|
||||||
|
extern std::map<PHLWINDOWREF, CWobblyWindow> g_wobblyWindows;
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
|
||||||
|
|
||||||
inline HANDLE PHANDLE = nullptr;
|
|
||||||
85
include/renderpasses.h
Normal file
85
include/renderpasses.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef WW_RENDERPASSES_H
|
||||||
|
#define WW_RENDERPASSES_H
|
||||||
|
|
||||||
|
#include <hyprland/src/desktop/Window.hpp>
|
||||||
|
#include <hyprland/src/render/Framebuffer.hpp>
|
||||||
|
#include <hyprland/src/render/OpenGL.hpp>
|
||||||
|
#include <hyprland/src/render/pass/PassElement.hpp>
|
||||||
|
|
||||||
|
class CBindOwnFramebufferPassElement final: public IPassElement {
|
||||||
|
public:
|
||||||
|
explicit CBindOwnFramebufferPassElement(CFramebuffer* pFramebuffer) :
|
||||||
|
m_pFramebuffer {pFramebuffer} {}
|
||||||
|
|
||||||
|
void draw(const CRegion& damage) override;
|
||||||
|
|
||||||
|
bool needsLiveBlur() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsPrecomputeBlur() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* passName() override {
|
||||||
|
return "BIND_OWN_FRAMEBUFFER";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> boundingBox() override {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion opaqueRegion() override {
|
||||||
|
return CRegion {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CFramebuffer* m_pFramebuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CRenderWobblyWindowPassElement final: public IPassElement {
|
||||||
|
static inline SShader* s_shader {};
|
||||||
|
static inline constexpr unsigned int s_SUBDIVS = 8;
|
||||||
|
static_assert(s_SUBDIVS > 0);
|
||||||
|
|
||||||
|
static inline GLuint s_VAO, s_VBO, s_VBO_UVs, s_EBO;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static inline std::vector<float> s_baseVerts;
|
||||||
|
|
||||||
|
explicit CRenderWobblyWindowPassElement(CFramebuffer* pOldFramebuffer, PHLWINDOWREF pWindow) :
|
||||||
|
m_pOldFramebuffer {pOldFramebuffer},
|
||||||
|
m_pWindow {pWindow} {}
|
||||||
|
|
||||||
|
static void initGPUObjects();
|
||||||
|
|
||||||
|
void draw(const CRegion& damage) override;
|
||||||
|
|
||||||
|
bool needsLiveBlur() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsPrecomputeBlur() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* passName() override {
|
||||||
|
return "RENDER_WOBBLY_WINDOW";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> boundingBox() override {
|
||||||
|
return g_pHyprOpenGL->m_renderData.pMonitor->logicalBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion opaqueRegion() override {
|
||||||
|
return CRegion {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CFramebuffer* m_pOldFramebuffer;
|
||||||
|
PHLWINDOWREF m_pWindow;
|
||||||
|
|
||||||
|
static inline SShader* s_pShader = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
32
include/wobblywindow.h
Normal file
32
include/wobblywindow.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef WW_WOBBLYWINDOW_H
|
||||||
|
#define WW_WOBBLYWINDOW_H
|
||||||
|
|
||||||
|
#include "renderpasses.h"
|
||||||
|
|
||||||
|
#include <hyprland/src/Compositor.hpp>
|
||||||
|
#include <hyprutils/math/Vector2D.hpp>
|
||||||
|
|
||||||
|
class CWobblyWindow {
|
||||||
|
struct SParticle {
|
||||||
|
Vector2D position;
|
||||||
|
Vector2D velocity;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time::steady_tp m_lastTime {Time::steadyNow()};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// static wobble parameters
|
||||||
|
static inline float s_springStrength = 500.f;
|
||||||
|
static inline float s_dampingStrength = 12.f;
|
||||||
|
static inline float s_drag = 0.4f;
|
||||||
|
|
||||||
|
std::vector<SParticle> m_particles;
|
||||||
|
std::vector<Vector2D> m_targetPositions;
|
||||||
|
std::optional<Vector2D> m_grabPosition {std::nullopt};
|
||||||
|
Vector2D m_windowMovement;
|
||||||
|
|
||||||
|
CWobblyWindow();
|
||||||
|
|
||||||
|
bool step(Time::steady_tp time);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
358
src/main.cpp
358
src/main.cpp
@ -1,12 +1,12 @@
|
|||||||
#include "globals.hpp"
|
#include "globals.h"
|
||||||
|
#include "renderpasses.h"
|
||||||
|
#include "version.hpp" // generated by meson
|
||||||
|
#include "wobblywindow.h"
|
||||||
|
|
||||||
#include <GLES3/gl32.h>
|
#include <GLES3/gl32.h>
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <hyprgraphics/color/Color.hpp>
|
#include <hyprgraphics/color/Color.hpp>
|
||||||
// version.hpp will be generated by meson
|
|
||||||
#include "version.hpp"
|
|
||||||
|
|
||||||
#include <hyprland/src/Compositor.hpp>
|
#include <hyprland/src/Compositor.hpp>
|
||||||
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||||
#include <hyprland/src/desktop/Window.hpp>
|
#include <hyprland/src/desktop/Window.hpp>
|
||||||
@ -30,261 +30,9 @@ APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
|||||||
return HYPRLAND_API_VERSION;
|
return HYPRLAND_API_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
SShader* g_shader {};
|
std::map<PHLWINDOWREF, CFramebuffer> g_windowFramebuffers;
|
||||||
|
std::map<PHLWINDOWREF, Vector2D> g_windowPositions;
|
||||||
constexpr unsigned int g_SUBDIVS = 8;
|
std::map<PHLWINDOWREF, CWobblyWindow> g_wobblyWindows;
|
||||||
static_assert(g_SUBDIVS > 0);
|
|
||||||
|
|
||||||
GLuint g_VAO, g_VBO, g_VBO_UVs, g_EBO;
|
|
||||||
std::vector<float> g_baseVerts;
|
|
||||||
unsigned int g_indexCount = 0;
|
|
||||||
|
|
||||||
class CBindOwnFramebufferPassElement final: public IPassElement {
|
|
||||||
public:
|
|
||||||
explicit CBindOwnFramebufferPassElement(CFramebuffer* pFramebuffer) :
|
|
||||||
m_pFramebuffer {pFramebuffer} {}
|
|
||||||
|
|
||||||
void draw(const CRegion& damage) override {
|
|
||||||
m_pFramebuffer->bind();
|
|
||||||
g_pHyprOpenGL->m_renderData.currentFB = m_pFramebuffer;
|
|
||||||
|
|
||||||
GLCALL(glClearColor(0, 0, 0, 0));
|
|
||||||
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsLiveBlur() override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsPrecomputeBlur() override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* passName() override {
|
|
||||||
return "BIND_OWN_FRAMEBUFFER";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<CBox> boundingBox() override {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRegion opaqueRegion() override {
|
|
||||||
return CRegion {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CFramebuffer* m_pFramebuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CWobblyWindow {
|
|
||||||
struct SParticle {
|
|
||||||
Vector2D position;
|
|
||||||
Vector2D velocity;
|
|
||||||
};
|
|
||||||
|
|
||||||
Time::steady_tp m_lastTime {Time::steadyNow()};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// static wobble parameters
|
|
||||||
static inline float s_springStrength = 500.f;
|
|
||||||
static inline float s_dampingStrength = 12.f;
|
|
||||||
static inline float s_drag = 0.4f;
|
|
||||||
|
|
||||||
std::vector<SParticle> m_particles;
|
|
||||||
std::vector<Vector2D> m_targetPositions;
|
|
||||||
std::optional<Vector2D> m_grabPosition {std::nullopt};
|
|
||||||
Vector2D m_windowMovement;
|
|
||||||
|
|
||||||
CWobblyWindow() {
|
|
||||||
m_particles.reserve(g_baseVerts.size() / 2);
|
|
||||||
m_targetPositions.reserve(g_baseVerts.size() / 2);
|
|
||||||
|
|
||||||
for (unsigned int i {}; i < g_baseVerts.size(); i += 2) {
|
|
||||||
m_particles.push_back(SParticle {Vector2D {g_baseVerts[i], g_baseVerts[i + 1]}, {}});
|
|
||||||
m_targetPositions.push_back(Vector2D {g_baseVerts[i], g_baseVerts[i + 1]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool step(Time::steady_tp time) {
|
|
||||||
const auto usec =
|
|
||||||
std::chrono::duration_cast<std::chrono::microseconds>(time - m_lastTime).count();
|
|
||||||
const float dt = std::min(0.016f, usec * 0.000001f);
|
|
||||||
m_lastTime = time;
|
|
||||||
|
|
||||||
Vector2D totalVel {};
|
|
||||||
|
|
||||||
for (unsigned int i {}; i < m_particles.size(); i++) {
|
|
||||||
auto&& particle = m_particles[i];
|
|
||||||
auto&& particlePositon = particle.position;
|
|
||||||
auto&& targetPosition = m_targetPositions[i];
|
|
||||||
|
|
||||||
const Vector2D directionToTarget = targetPosition - particlePositon;
|
|
||||||
|
|
||||||
if (m_grabPosition.has_value()) {
|
|
||||||
const float distanceToDragPosition =
|
|
||||||
m_grabPosition.value().distance(particlePositon);
|
|
||||||
const float dragStrength = std::clamp(distanceToDragPosition, 0.f, 1.f);
|
|
||||||
|
|
||||||
particle.position += m_windowMovement * dragStrength;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector2D springForce =
|
|
||||||
directionToTarget * s_springStrength - particle.velocity * s_dampingStrength;
|
|
||||||
particle.velocity += springForce * dt;
|
|
||||||
|
|
||||||
// Apply drag
|
|
||||||
const Vector2D dragForceVector = (particle.velocity * particle.velocity) * -s_drag;
|
|
||||||
|
|
||||||
// * Area
|
|
||||||
auto dir = particle.velocity;
|
|
||||||
float magnitude = dir.normalize();
|
|
||||||
|
|
||||||
if (magnitude != 0)
|
|
||||||
particle.velocity += (dragForceVector * dir) * dt;
|
|
||||||
|
|
||||||
// Apply velocity
|
|
||||||
particle.position += particle.velocity * dt;
|
|
||||||
|
|
||||||
totalVel += particle.velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool shouldEnd =
|
|
||||||
m_windowMovement.size() == 0 and totalVel.size() / m_particles.size() < .001f;
|
|
||||||
|
|
||||||
// std::println(
|
|
||||||
// "Top left: {}, totalVel: {}",
|
|
||||||
// m_particles[0].position,
|
|
||||||
// totalVel.size() / m_particles.size()
|
|
||||||
// );
|
|
||||||
m_windowMovement = Vector2D {};
|
|
||||||
|
|
||||||
return shouldEnd;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::map<PHLWINDOWREF, CFramebuffer> g_windowFramebuffers;
|
|
||||||
inline std::map<PHLWINDOWREF, Vector2D> g_windowPositions;
|
|
||||||
inline std::map<PHLWINDOWREF, CWobblyWindow> g_wobblyWindows;
|
|
||||||
|
|
||||||
class CRenderWobblyWindowPassElement final: public IPassElement {
|
|
||||||
public:
|
|
||||||
explicit CRenderWobblyWindowPassElement(CFramebuffer* pOldFramebuffer, PHLWINDOWREF pWindow) :
|
|
||||||
m_pOldFramebuffer {pOldFramebuffer},
|
|
||||||
m_pWindow {pWindow} {}
|
|
||||||
|
|
||||||
void draw(const CRegion& damage) override {
|
|
||||||
auto* const pWindowFB = g_pHyprOpenGL->m_renderData.currentFB;
|
|
||||||
|
|
||||||
m_pOldFramebuffer->bind();
|
|
||||||
g_pHyprOpenGL->m_renderData.currentFB = m_pOldFramebuffer;
|
|
||||||
|
|
||||||
const auto windowBox = m_pWindow->getFullWindowBoundingBox();
|
|
||||||
|
|
||||||
CBox newBox = windowBox;
|
|
||||||
g_pHyprOpenGL->m_renderData.renderModif.applyToBox(newBox);
|
|
||||||
|
|
||||||
// get transform
|
|
||||||
const auto TRANSFORM =
|
|
||||||
wlTransformToHyprutils(invertTransform(g_pHyprOpenGL->m_renderData.pMonitor->m_transform
|
|
||||||
));
|
|
||||||
|
|
||||||
Mat3x3 matrix =
|
|
||||||
g_pHyprOpenGL->m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot);
|
|
||||||
Mat3x3 glMatrix = g_pHyprOpenGL->m_renderData.projection.copy().multiply(matrix);
|
|
||||||
|
|
||||||
GLCALL(glActiveTexture(GL_TEXTURE0));
|
|
||||||
pWindowFB->getTexture()->bind();
|
|
||||||
|
|
||||||
g_pHyprOpenGL->useProgram(g_shader->program);
|
|
||||||
g_shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
|
|
||||||
g_shader->setUniformInt(SHADER_TEX, 0);
|
|
||||||
|
|
||||||
GLCALL(glBindVertexArray(g_VAO));
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO));
|
|
||||||
|
|
||||||
// TODO: can we avoid this entirely by rendering the window to framebuffer pos 0,0?
|
|
||||||
const Vector2D UVTopLeft = Vector2D {windowBox.x, windowBox.y} / pWindowFB->m_size;
|
|
||||||
const Vector2D UVBottomRight =
|
|
||||||
Vector2D {windowBox.x + windowBox.width, windowBox.y + windowBox.height}
|
|
||||||
/ pWindowFB->m_size;
|
|
||||||
|
|
||||||
const unsigned int vertsPerRow = g_SUBDIVS + 1;
|
|
||||||
std::vector<float> UVs;
|
|
||||||
UVs.reserve(vertsPerRow * vertsPerRow * 2);
|
|
||||||
|
|
||||||
const auto step = (UVBottomRight - UVTopLeft) / (g_SUBDIVS);
|
|
||||||
|
|
||||||
for (unsigned int y = 0; y < vertsPerRow; ++y) {
|
|
||||||
const float v = UVTopLeft.y + y * step.y;
|
|
||||||
for (unsigned int x = 0; x < vertsPerRow; ++x) {
|
|
||||||
const float u = UVTopLeft.x + x * step.x;
|
|
||||||
|
|
||||||
UVs.push_back(u);
|
|
||||||
UVs.push_back(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO_UVs));
|
|
||||||
GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, UVs.size() * sizeof(float), UVs.data()));
|
|
||||||
|
|
||||||
if (g_wobblyWindows.contains(m_pWindow)) {
|
|
||||||
auto&& wobble = g_wobblyWindows[m_pWindow];
|
|
||||||
|
|
||||||
// TODO: these should never be nan
|
|
||||||
// if (not std::isnan(wobble.m_particles[0].position.x)) {
|
|
||||||
// TODO: we need the particle positions in their own vec, to avoid this copy
|
|
||||||
std::vector<float> verts;
|
|
||||||
verts.reserve(vertsPerRow * vertsPerRow * 2);
|
|
||||||
for (auto&& particle : wobble.m_particles) {
|
|
||||||
verts.push_back(particle.position.x);
|
|
||||||
verts.push_back(particle.position.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO));
|
|
||||||
GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, verts.size() * sizeof(float), verts.data()));
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
// restore default verts
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO));
|
|
||||||
GLCALL(glBufferSubData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
0,
|
|
||||||
g_baseVerts.size() * sizeof(float),
|
|
||||||
g_baseVerts.data()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_EBO));
|
|
||||||
GLCALL(glDrawElements(GL_TRIANGLE_STRIP, g_indexCount, GL_UNSIGNED_INT, 0));
|
|
||||||
|
|
||||||
GLCALL(glBindVertexArray(0));
|
|
||||||
pWindowFB->getTexture()->unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsLiveBlur() override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsPrecomputeBlur() override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* passName() override {
|
|
||||||
return "RENDER_WOBBLY_WINDOW";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<CBox> boundingBox() override {
|
|
||||||
return g_pHyprOpenGL->m_renderData.pMonitor->logicalBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
CRegion opaqueRegion() override {
|
|
||||||
return CRegion {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CFramebuffer* m_pOldFramebuffer;
|
|
||||||
PHLWINDOWREF m_pWindow;
|
|
||||||
};
|
|
||||||
|
|
||||||
void registerWindow(PHLWINDOW pWindow) {
|
void registerWindow(PHLWINDOW pWindow) {
|
||||||
g_windowPositions[pWindow] = pWindow->m_realPosition->value();
|
g_windowPositions[pWindow] = pWindow->m_realPosition->value();
|
||||||
@ -404,95 +152,6 @@ void hkRenderWindow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initGPUObjects() {
|
|
||||||
g_shader = &g_pHyprOpenGL->m_shaders->m_shRGBA;
|
|
||||||
|
|
||||||
// std::vector<float> finalVerts;
|
|
||||||
const unsigned int vertsPerRow = g_SUBDIVS + 1;
|
|
||||||
g_baseVerts.reserve(vertsPerRow * vertsPerRow * 2);
|
|
||||||
|
|
||||||
const float step = 1.f / (g_SUBDIVS);
|
|
||||||
for (unsigned int y = 0; y < vertsPerRow; ++y) {
|
|
||||||
for (unsigned int x = 0; x < vertsPerRow; ++x) {
|
|
||||||
g_baseVerts.push_back(x * step);
|
|
||||||
g_baseVerts.push_back(y * step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GLuint> indices;
|
|
||||||
g_indexCount = 3 * 2 * g_SUBDIVS * g_SUBDIVS;
|
|
||||||
indices.reserve(g_indexCount);
|
|
||||||
|
|
||||||
for (int y = 0; y < g_SUBDIVS; ++y) {
|
|
||||||
for (int x = 0; x < g_SUBDIVS; ++x) {
|
|
||||||
indices.push_back(y * vertsPerRow + x + 1); // top right
|
|
||||||
indices.push_back(y * vertsPerRow + x); // top left
|
|
||||||
indices.push_back((y + 1) * vertsPerRow + x + 1); // bottom right
|
|
||||||
|
|
||||||
indices.push_back(y * vertsPerRow + x); // top left
|
|
||||||
indices.push_back((y + 1) * vertsPerRow + x); // bottom left
|
|
||||||
indices.push_back((y + 1) * vertsPerRow + x + 1); // bottom right
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glGenVertexArrays(1, &g_VAO));
|
|
||||||
GLCALL(glGenBuffers(1, &g_VBO));
|
|
||||||
GLCALL(glGenBuffers(1, &g_VBO_UVs));
|
|
||||||
GLCALL(glGenBuffers(1, &g_EBO));
|
|
||||||
|
|
||||||
GLCALL(glBindVertexArray(g_VAO));
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_EBO));
|
|
||||||
GLCALL(glBufferData(
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER,
|
|
||||||
indices.size() * sizeof(GLuint),
|
|
||||||
indices.data(),
|
|
||||||
GL_STATIC_DRAW
|
|
||||||
));
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO));
|
|
||||||
{
|
|
||||||
GLCALL(glBufferData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
g_baseVerts.size() * sizeof(float),
|
|
||||||
g_baseVerts.data(),
|
|
||||||
GL_DYNAMIC_DRAW
|
|
||||||
));
|
|
||||||
|
|
||||||
GLCALL(glEnableVertexAttribArray(g_shader->uniformLocations[SHADER_POS_ATTRIB]));
|
|
||||||
GLCALL(glVertexAttribPointer(
|
|
||||||
g_shader->uniformLocations[SHADER_POS_ATTRIB],
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
0,
|
|
||||||
nullptr
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, g_VBO_UVs));
|
|
||||||
{
|
|
||||||
GLCALL(glBufferData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
g_baseVerts.size() * sizeof(float),
|
|
||||||
g_baseVerts.data(),
|
|
||||||
GL_DYNAMIC_DRAW
|
|
||||||
)); // Initial dummy UVs
|
|
||||||
GLCALL(glEnableVertexAttribArray(g_shader->uniformLocations[SHADER_TEX_ATTRIB]));
|
|
||||||
GLCALL(glVertexAttribPointer(
|
|
||||||
g_shader->uniformLocations[SHADER_TEX_ATTRIB],
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
0,
|
|
||||||
nullptr
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindVertexArray(0));
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
PHANDLE = handle;
|
PHANDLE = handle;
|
||||||
|
|
||||||
@ -510,7 +169,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
|||||||
throw std::runtime_error("[WiggleWobble] Version mismatch");
|
throw std::runtime_error("[WiggleWobble] Version mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
initGPUObjects();
|
CRenderWobblyWindowPassElement::initGPUObjects();
|
||||||
|
|
||||||
for (auto&& window : g_pCompositor->m_windows)
|
for (auto&& window : g_pCompositor->m_windows)
|
||||||
registerWindow(window);
|
registerWindow(window);
|
||||||
@ -549,6 +208,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APICALL EXPORT void PLUGIN_EXIT() {
|
APICALL EXPORT void PLUGIN_EXIT() {
|
||||||
|
// TODO: CRenderWobblyWindowPassElement::deinitGPUObjects();
|
||||||
g_pRenderWindowHook = nullptr;
|
g_pRenderWindowHook = nullptr;
|
||||||
g_openWindow = nullptr;
|
g_openWindow = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
shared_module('wigglewobble',
|
shared_module('wigglewobble',
|
||||||
'main.cpp',
|
['main.cpp','wobblywindow.cpp','renderpasses.cpp'],
|
||||||
cpp_args: ['-DWLR_USE_UNSTABLE'],
|
cpp_args: ['-DWLR_USE_UNSTABLE'],
|
||||||
include_directories: incdir,
|
include_directories: incdir,
|
||||||
# sometimes you need to add other hyprland dependencies yourself
|
# sometimes you need to add other hyprland dependencies yourself
|
||||||
|
|||||||
187
src/renderpasses.cpp
Normal file
187
src/renderpasses.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include "renderpasses.h"
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
#include "wobblywindow.h"
|
||||||
|
|
||||||
|
void CBindOwnFramebufferPassElement::draw(const CRegion& damage) {
|
||||||
|
m_pFramebuffer->bind();
|
||||||
|
g_pHyprOpenGL->m_renderData.currentFB = m_pFramebuffer;
|
||||||
|
|
||||||
|
GLCALL(glClearColor(0, 0, 0, 0));
|
||||||
|
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderWobblyWindowPassElement::initGPUObjects() {
|
||||||
|
s_pShader = &g_pHyprOpenGL->m_shaders->m_shRGBA;
|
||||||
|
|
||||||
|
const unsigned int vertsPerRow = s_SUBDIVS + 1;
|
||||||
|
s_baseVerts.reserve(vertsPerRow * vertsPerRow * 2);
|
||||||
|
|
||||||
|
const float step = 1.f / (s_SUBDIVS);
|
||||||
|
for (unsigned int y = 0; y < vertsPerRow; ++y) {
|
||||||
|
for (unsigned int x = 0; x < vertsPerRow; ++x) {
|
||||||
|
s_baseVerts.push_back(x * step);
|
||||||
|
s_baseVerts.push_back(y * step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GLuint> indices;
|
||||||
|
indices.reserve(3 * 2 * s_SUBDIVS * s_SUBDIVS);
|
||||||
|
|
||||||
|
for (int y = 0; y < s_SUBDIVS; ++y) {
|
||||||
|
for (int x = 0; x < s_SUBDIVS; ++x) {
|
||||||
|
indices.push_back(y * vertsPerRow + x + 1); // top right
|
||||||
|
indices.push_back(y * vertsPerRow + x); // top left
|
||||||
|
indices.push_back((y + 1) * vertsPerRow + x + 1); // bottom right
|
||||||
|
|
||||||
|
indices.push_back(y * vertsPerRow + x); // top left
|
||||||
|
indices.push_back((y + 1) * vertsPerRow + x); // bottom left
|
||||||
|
indices.push_back((y + 1) * vertsPerRow + x + 1); // bottom right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glGenVertexArrays(1, &s_VAO));
|
||||||
|
GLCALL(glGenBuffers(1, &s_VBO));
|
||||||
|
GLCALL(glGenBuffers(1, &s_VBO_UVs));
|
||||||
|
GLCALL(glGenBuffers(1, &s_EBO));
|
||||||
|
|
||||||
|
GLCALL(glBindVertexArray(s_VAO));
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_EBO));
|
||||||
|
GLCALL(glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
indices.size() * sizeof(GLuint),
|
||||||
|
indices.data(),
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
));
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
||||||
|
{
|
||||||
|
GLCALL(glBufferData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
s_baseVerts.size() * sizeof(float),
|
||||||
|
s_baseVerts.data(),
|
||||||
|
GL_DYNAMIC_DRAW
|
||||||
|
));
|
||||||
|
|
||||||
|
GLCALL(glEnableVertexAttribArray(s_pShader->uniformLocations[SHADER_POS_ATTRIB]));
|
||||||
|
GLCALL(glVertexAttribPointer(
|
||||||
|
s_pShader->uniformLocations[SHADER_POS_ATTRIB],
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO_UVs));
|
||||||
|
{
|
||||||
|
GLCALL(glBufferData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
s_baseVerts.size() * sizeof(float),
|
||||||
|
s_baseVerts.data(),
|
||||||
|
GL_DYNAMIC_DRAW
|
||||||
|
)); // Initial dummy UVs
|
||||||
|
GLCALL(glEnableVertexAttribArray(s_pShader->uniformLocations[SHADER_TEX_ATTRIB]));
|
||||||
|
GLCALL(glVertexAttribPointer(
|
||||||
|
s_pShader->uniformLocations[SHADER_TEX_ATTRIB],
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glBindVertexArray(0));
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderWobblyWindowPassElement::draw(const CRegion& damage) {
|
||||||
|
auto* const pWindowFB = g_pHyprOpenGL->m_renderData.currentFB;
|
||||||
|
|
||||||
|
m_pOldFramebuffer->bind();
|
||||||
|
g_pHyprOpenGL->m_renderData.currentFB = m_pOldFramebuffer;
|
||||||
|
|
||||||
|
const auto windowBox = m_pWindow->getFullWindowBoundingBox();
|
||||||
|
|
||||||
|
CBox newBox = windowBox;
|
||||||
|
g_pHyprOpenGL->m_renderData.renderModif.applyToBox(newBox);
|
||||||
|
|
||||||
|
// get transform
|
||||||
|
const auto TRANSFORM =
|
||||||
|
wlTransformToHyprutils(invertTransform(g_pHyprOpenGL->m_renderData.pMonitor->m_transform));
|
||||||
|
|
||||||
|
Mat3x3 matrix =
|
||||||
|
g_pHyprOpenGL->m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot);
|
||||||
|
Mat3x3 glMatrix = g_pHyprOpenGL->m_renderData.projection.copy().multiply(matrix);
|
||||||
|
|
||||||
|
GLCALL(glActiveTexture(GL_TEXTURE0));
|
||||||
|
pWindowFB->getTexture()->bind();
|
||||||
|
|
||||||
|
g_pHyprOpenGL->useProgram(s_pShader->program);
|
||||||
|
s_pShader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
|
||||||
|
s_pShader->setUniformInt(SHADER_TEX, 0);
|
||||||
|
|
||||||
|
GLCALL(glBindVertexArray(s_VAO));
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
||||||
|
|
||||||
|
// TODO: can we avoid this entirely by rendering the window to framebuffer pos 0,0?
|
||||||
|
const Vector2D UVTopLeft = Vector2D {windowBox.x, windowBox.y} / pWindowFB->m_size;
|
||||||
|
const Vector2D UVBottomRight =
|
||||||
|
Vector2D {windowBox.x + windowBox.width, windowBox.y + windowBox.height}
|
||||||
|
/ pWindowFB->m_size;
|
||||||
|
|
||||||
|
const unsigned int vertsPerRow = s_SUBDIVS + 1;
|
||||||
|
std::vector<float> UVs;
|
||||||
|
UVs.reserve(vertsPerRow * vertsPerRow * 2);
|
||||||
|
|
||||||
|
const auto step = (UVBottomRight - UVTopLeft) / (s_SUBDIVS);
|
||||||
|
|
||||||
|
for (unsigned int y = 0; y < vertsPerRow; ++y) {
|
||||||
|
const float v = UVTopLeft.y + y * step.y;
|
||||||
|
for (unsigned int x = 0; x < vertsPerRow; ++x) {
|
||||||
|
const float u = UVTopLeft.x + x * step.x;
|
||||||
|
|
||||||
|
UVs.push_back(u);
|
||||||
|
UVs.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO_UVs));
|
||||||
|
GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, UVs.size() * sizeof(float), UVs.data()));
|
||||||
|
|
||||||
|
if (g_wobblyWindows.contains(m_pWindow)) {
|
||||||
|
auto&& wobble = g_wobblyWindows[m_pWindow];
|
||||||
|
|
||||||
|
// TODO: these should never be nan
|
||||||
|
// if (not std::isnan(wobble.m_particles[0].position.x)) {
|
||||||
|
// TODO: we need the particle positions in their own vec, to avoid this copy
|
||||||
|
std::vector<float> verts;
|
||||||
|
verts.reserve(vertsPerRow * vertsPerRow * 2);
|
||||||
|
for (auto&& particle : wobble.m_particles) {
|
||||||
|
verts.push_back(particle.position.x);
|
||||||
|
verts.push_back(particle.position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
||||||
|
GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, verts.size() * sizeof(float), verts.data()));
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
// restore default verts
|
||||||
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
||||||
|
GLCALL(glBufferSubData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
0,
|
||||||
|
s_baseVerts.size() * sizeof(float),
|
||||||
|
s_baseVerts.data()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_EBO));
|
||||||
|
GLCALL(glDrawElements(GL_TRIANGLE_STRIP, 3 * 2 * s_SUBDIVS * s_SUBDIVS, GL_UNSIGNED_INT, 0));
|
||||||
|
|
||||||
|
GLCALL(glBindVertexArray(0));
|
||||||
|
pWindowFB->getTexture()->unbind();
|
||||||
|
}
|
||||||
69
src/wobblywindow.cpp
Normal file
69
src/wobblywindow.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "wobblywindow.h"
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
CWobblyWindow::CWobblyWindow() {
|
||||||
|
auto&& verts = CRenderWobblyWindowPassElement::s_baseVerts;
|
||||||
|
m_particles.reserve(verts.size() / 2);
|
||||||
|
m_targetPositions.reserve(verts.size() / 2);
|
||||||
|
|
||||||
|
for (unsigned int i {}; i < verts.size(); i += 2) {
|
||||||
|
m_particles.push_back(SParticle {Vector2D {verts[i], verts[i + 1]}, {}});
|
||||||
|
m_targetPositions.push_back(Vector2D {verts[i], verts[i + 1]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWobblyWindow::step(Time::steady_tp time) {
|
||||||
|
const auto usec =
|
||||||
|
std::chrono::duration_cast<std::chrono::microseconds>(time - m_lastTime).count();
|
||||||
|
const float dt = std::min(0.016f, usec * 0.000001f);
|
||||||
|
m_lastTime = time;
|
||||||
|
|
||||||
|
Vector2D totalVel {};
|
||||||
|
|
||||||
|
for (unsigned int i {}; i < m_particles.size(); i++) {
|
||||||
|
auto&& particle = m_particles[i];
|
||||||
|
auto&& particlePositon = particle.position;
|
||||||
|
auto&& targetPosition = m_targetPositions[i];
|
||||||
|
|
||||||
|
const Vector2D directionToTarget = targetPosition - particlePositon;
|
||||||
|
|
||||||
|
if (m_grabPosition.has_value()) {
|
||||||
|
const float distanceToDragPosition = m_grabPosition.value().distance(particlePositon);
|
||||||
|
const float dragStrength = std::clamp(distanceToDragPosition, 0.f, 1.f);
|
||||||
|
|
||||||
|
particle.position += m_windowMovement * dragStrength;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector2D springForce =
|
||||||
|
directionToTarget * s_springStrength - particle.velocity * s_dampingStrength;
|
||||||
|
particle.velocity += springForce * dt;
|
||||||
|
|
||||||
|
// Apply drag
|
||||||
|
const Vector2D dragForceVector = (particle.velocity * particle.velocity) * -s_drag;
|
||||||
|
|
||||||
|
// * Area
|
||||||
|
auto dir = particle.velocity;
|
||||||
|
float magnitude = dir.normalize();
|
||||||
|
|
||||||
|
if (magnitude != 0)
|
||||||
|
particle.velocity += (dragForceVector * dir) * dt;
|
||||||
|
|
||||||
|
// Apply velocity
|
||||||
|
particle.position += particle.velocity * dt;
|
||||||
|
|
||||||
|
totalVel += particle.velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool shouldEnd =
|
||||||
|
m_windowMovement.size() == 0 and totalVel.size() / m_particles.size() < .001f;
|
||||||
|
|
||||||
|
// std::println(
|
||||||
|
// "Top left: {}, totalVel: {}",
|
||||||
|
// m_particles[0].position,
|
||||||
|
// totalVel.size() / m_particles.size()
|
||||||
|
// );
|
||||||
|
m_windowMovement = Vector2D {};
|
||||||
|
|
||||||
|
return shouldEnd;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user