abg

Animated background for X11
git clone git://git.laack.co/abg.git
Log | Files | Refs | README

commit d0820a8807f128e1fd25aa50d517bec869e61a54
parent 5dcc3776e04d7f245995055cf9621f1c86f28157
Author: Andrew Laack <andrew@laack.co>
Date:   Tue, 15 Sep 2026 00:51:14 -0500

Refactoring

Diffstat:
Dbackground/edge.cpp | 16----------------
Dbackground/graph.cpp | 119-------------------------------------------------------------------------------
Rbackground/edge.hpp -> background/headers/edge.hpp | 0
Rbackground/graph.hpp -> background/headers/graph.hpp | 0
Rbackground/utils.hpp -> background/headers/utils.hpp | 0
Rbackground/vertex.hpp -> background/headers/vertex.hpp | 0
Dbackground/main.cpp | 105-------------------------------------------------------------------------------
Rbackground/Makefile -> background/src/Makefile | 0
Abackground/src/edge.cpp | 16++++++++++++++++
Abackground/src/graph.cpp | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abackground/src/main.cpp | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abackground/src/utils.cpp | 20++++++++++++++++++++
Abackground/src/vertex.cpp | 21+++++++++++++++++++++
Dbackground/utils.cpp | 20--------------------
Dbackground/vertex.cpp | 21---------------------
15 files changed, 280 insertions(+), 281 deletions(-)

diff --git a/background/edge.cpp b/background/edge.cpp @@ -1,16 +0,0 @@ -#include "edge.hpp" - -Edge::Edge(std::size_t v1, std::size_t v2, float length2) - : v1Index(v1), v2Index(v2), length2(length2) {} - -std::string Edge::toString() { - return "(" + std::to_string(this->v1Index) + ", " + std::to_string(this->v2Index) + ")"; -} - -bool Edge::operator<(const Edge& other) const { - return length2 < other.length2; -} - -bool Edge::operator>(const Edge& other) const { - return length2 > other.length2; -} diff --git a/background/graph.cpp b/background/graph.cpp @@ -1,119 +0,0 @@ -#include "graph.hpp" -#include "vertex.hpp" -#include "utils.hpp" -#include <cstddef> -#include <raylib.h> -#include <iostream> - -Graph::Graph(std::size_t edgeCount, std::size_t vertCount, float xMax, float yMax) { - for(std::size_t i = 0; i < vertCount; ++i) { - Vector2 rnd = randomPosition(xMax, yMax); - Vertex v {rnd,5}; - this->vertices.push_back(v); - } - for(std::size_t i = 0; i < edgeCount; ++i) { - std::size_t idx1 = 0; - std::size_t idx2 = 0; - // no self-edges - while (idx1 == idx2) { - idx1 = std::rand() % vertCount; - idx2 = std::rand() % vertCount; - } - - Edge e {idx1, idx2, distanceSquared(vertices[idx1].position, vertices[idx2].position)}; - this->edges[idx1].push_back(e); - this->edges[idx2].push_back(e); - } -} - -std::string Graph::toString() { - - std::string result = "edges: {"; - - for(auto pair: this->edges) { - auto key = pair.first; - for(auto edge: edges[key]) { - result += edge.toString(); - } - } - - result += "}"; - - result += "\nvertices: {"; - - for(auto vertex: this->vertices) { - result += vertex.toString(); - } - - result += "}"; - return result; -} - - -void Graph::render() { - // yes, this will double draw because we track 0 -> 1 and 1 -> 0 - - std::vector<Edge> visited {}; - for(auto pair: this->edges) { - auto edges = this->edges[pair.first]; - for(auto edge: edges) { - std::size_t idx1 = edge.v1Index; - std::size_t idx2 = edge.v2Index; - auto v1 = vertices[idx1].position; - auto v2 = vertices[idx2].position; - if(edge.traversed) { - visited.push_back(edge); - } else { - DrawLineEx(v1, v2, 1,DARKERGRAY); - } - } - } - - for(auto vertex: this->vertices) { - vertex.render(); - } - - // ensure we draw visited over unvisited for better looks - for(auto edge: visited) { - std::size_t idx1 = edge.v1Index; - std::size_t idx2 = edge.v2Index; - auto v1 = vertices[idx1].position; - auto v2 = vertices[idx2].position; - DrawLineEx(v1, v2, 1, WHITE); - } -} - -void Graph::traverseVertexIdx(std::size_t idx) { - this->vertices[idx].visited = true; -} - -std::vector<Edge> Graph::getEdgesOfVertexIdx(std::size_t idx) { - return this->edges[idx]; -} - -void Graph::setEdgeTraversed(Edge e) { - - std::size_t source = e.v1Index; - std::size_t destination = e.v2Index; - - if(source == destination) { - return; - } - - auto& cEdges = edges[source]; - - for(auto& edge : cEdges) { - if(edge.v2Index == destination || edge.v1Index == destination) { - edge.traversed = true; - } - } - - auto& oEdges = edges[destination]; - - for(auto& edge : oEdges) { - if(edge.v2Index == source || edge.v1Index == source) { - edge.traversed = true; - } - } - -} diff --git a/background/edge.hpp b/background/headers/edge.hpp diff --git a/background/graph.hpp b/background/headers/graph.hpp diff --git a/background/utils.hpp b/background/headers/utils.hpp diff --git a/background/vertex.hpp b/background/headers/vertex.hpp diff --git a/background/main.cpp b/background/main.cpp @@ -1,105 +0,0 @@ -#include "graph.hpp" -#include <cstdlib> -#include <unistd.h> -#include <raylib.h> -#include <ctime> -#include <queue> -#include <unordered_set> -#include <filesystem> - - -void CustomTakeScreenshot(char* filePath){ - const char *customParam; - Image screenshot = LoadImageFromScreen(); - ExportImage(screenshot, TextFormat(filePath, customParam)); - UnloadImage(screenshot); -} -void explore( - std::size_t cIdx, - std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>>& toVisit, - Edge& current, - Graph& g - ) { - g.traverseVertexIdx(cIdx); - std::vector<Edge> edges = g.getEdgesOfVertexIdx(cIdx); - for(auto edge: edges) { - toVisit.push(edge); - } - g.setEdgeTraversed(current); -} - -int main() { - - std::filesystem::create_directory("/dev/shm/bg"); - srand(clock()); - - std::size_t edgeCount = 30; - std::size_t vertCount = 10; - - float xMax = 5120; - float yMax = 1440; - - SetConfigFlags(FLAG_WINDOW_HIDDEN); - InitWindow(xMax, yMax, "Raylib animation window"); - - while (!WindowShouldClose()) { - - Graph g = Graph(edgeCount, vertCount, xMax,yMax); - std::unordered_set<std::size_t> visitedIndices {}; - std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> toVisit {}; - std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); - - for(auto edge: edges) { - toVisit.push(edge); - } - - g.traverseVertexIdx(0); - visitedIndices.insert(0); - - while (!WindowShouldClose()) { - sleep(5); - - BeginDrawing(); - ClearBackground(BLACK); - g.render(); - EndDrawing(); - - char path[] = "/dev/shm/bg/out.png"; - CustomTakeScreenshot(path); - // TODO: Can this be done away with? It's not *that* slow... - system("/usr/bin/feh --no-fehbg --bg-tile /dev/shm/bg/out.png"); - - - bool found = false; - if(toVisit.size() == 0) { - break; - } - while(found == false) { - if(toVisit.size() == 0) { - break; - } - - found = true; - auto current = toVisit.top(); - toVisit.pop(); - - if(visitedIndices.find(current.v2Index) == visitedIndices.end()) { - auto cIdx = current.v2Index; - visitedIndices.insert(current.v2Index); - explore(cIdx, toVisit, current, g); - - } else if(visitedIndices.find(current.v1Index) == visitedIndices.end()) { - auto cIdx = current.v1Index; - visitedIndices.insert(current.v1Index); - explore(cIdx, toVisit, current, g); - } else { - found = false; - } - - } - - } - - } - -} diff --git a/background/Makefile b/background/src/Makefile diff --git a/background/src/edge.cpp b/background/src/edge.cpp @@ -0,0 +1,16 @@ +#include "../headers/edge.hpp" + +Edge::Edge(std::size_t v1, std::size_t v2, float length2) + : v1Index(v1), v2Index(v2), length2(length2) {} + +std::string Edge::toString() { + return "(" + std::to_string(this->v1Index) + ", " + std::to_string(this->v2Index) + ")"; +} + +bool Edge::operator<(const Edge& other) const { + return length2 < other.length2; +} + +bool Edge::operator>(const Edge& other) const { + return length2 > other.length2; +} diff --git a/background/src/graph.cpp b/background/src/graph.cpp @@ -0,0 +1,119 @@ +#include "../headers/graph.hpp" +#include "../headers/vertex.hpp" +#include "../headers/utils.hpp" +#include <cstddef> +#include <raylib.h> + +Graph::Graph(std::size_t edgeCount, std::size_t vertCount, float xMax, float yMax) { + for(std::size_t i = 0; i < vertCount; ++i) { + Vector2 rnd = randomPosition(xMax, yMax); + Vertex v {rnd,5}; + this->vertices.push_back(v); + } + for(std::size_t i = 0; i < edgeCount; ++i) { + std::size_t idx1 = 0; + std::size_t idx2 = 0; + // no self-edges + while (idx1 == idx2) { + idx1 = std::rand() % vertCount; + idx2 = std::rand() % vertCount; + } + + Edge e {idx1, idx2, distanceSquared(vertices[idx1].position, vertices[idx2].position)}; + this->edges[idx1].push_back(e); + this->edges[idx2].push_back(e); + } +} + +std::string Graph::toString() { + + std::string result = "edges: {"; + + for(auto pair: this->edges) { + auto key = pair.first; + for(auto edge: edges[key]) { + result += edge.toString(); + } + } + + result += "}"; + + result += "\nvertices: {"; + + for(auto vertex: this->vertices) { + result += vertex.toString(); + } + + result += "}"; + return result; +} + + +void Graph::render() { + + // yes, this will double draw because we track 0 -> 1 and 1 -> 0 + + std::vector<Edge> visited {}; + for(auto pair: this->edges) { + auto edges = this->edges[pair.first]; + for(auto edge: edges) { + std::size_t idx1 = edge.v1Index; + std::size_t idx2 = edge.v2Index; + auto v1 = vertices[idx1].position; + auto v2 = vertices[idx2].position; + if(edge.traversed) { + visited.push_back(edge); + } else { + DrawLineEx(v1, v2, 1,DARKERGRAY); + } + } + } + + for(auto vertex: this->vertices) { + vertex.render(); + } + + // ensure we draw visited over unvisited for better looks + for(auto edge: visited) { + std::size_t idx1 = edge.v1Index; + std::size_t idx2 = edge.v2Index; + auto v1 = vertices[idx1].position; + auto v2 = vertices[idx2].position; + DrawLineEx(v1, v2, 1, WHITE); + } +} + +void Graph::traverseVertexIdx(std::size_t idx) { + this->vertices[idx].visited = true; +} + +std::vector<Edge> Graph::getEdgesOfVertexIdx(std::size_t idx) { + return this->edges[idx]; +} + +void Graph::setEdgeTraversed(Edge e) { + + std::size_t source = e.v1Index; + std::size_t destination = e.v2Index; + + if(source == destination) { + return; + } + + auto& cEdges = edges[source]; + + for(auto& edge : cEdges) { + if(edge.v2Index == destination || edge.v1Index == destination) { + edge.traversed = true; + } + } + + auto& oEdges = edges[destination]; + + for(auto& edge : oEdges) { + if(edge.v2Index == source || edge.v1Index == source) { + edge.traversed = true; + } + } + +} diff --git a/background/src/main.cpp b/background/src/main.cpp @@ -0,0 +1,104 @@ +#include "../headers/graph.hpp" +#include <cstdlib> +#include <unistd.h> +#include <raylib.h> +#include <ctime> +#include <queue> +#include <unordered_set> +#include <filesystem> + +void CustomTakeScreenshot(char* filePath){ + const char *customParam; + Image screenshot = LoadImageFromScreen(); + ExportImage(screenshot, TextFormat(filePath, customParam)); + UnloadImage(screenshot); +} +void explore( + std::size_t cIdx, + std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>>& toVisit, + Edge& current, + Graph& g + ) { + g.traverseVertexIdx(cIdx); + std::vector<Edge> edges = g.getEdgesOfVertexIdx(cIdx); + for(auto edge: edges) { + toVisit.push(edge); + } + g.setEdgeTraversed(current); +} + +int main() { + + std::filesystem::create_directory("/dev/shm/bg"); + srand(clock()); + + std::size_t edgeCount = 30; + std::size_t vertCount = 10; + + float xMax = 5120; + float yMax = 1440; + + SetConfigFlags(FLAG_WINDOW_HIDDEN); + InitWindow(xMax, yMax, "Raylib animation window"); + + while (!WindowShouldClose()) { + + Graph g = Graph(edgeCount, vertCount, xMax,yMax); + std::unordered_set<std::size_t> visitedIndices {}; + std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> toVisit {}; + std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); + + for(auto edge: edges) { + toVisit.push(edge); + } + + g.traverseVertexIdx(0); + visitedIndices.insert(0); + + while (!WindowShouldClose()) { + sleep(5); + + BeginDrawing(); + ClearBackground(BLACK); + g.render(); + EndDrawing(); + + char path[] = "/dev/shm/bg/out.png"; + CustomTakeScreenshot(path); + // TODO: Can this be done away with? It's not *that* slow... + system("/usr/bin/feh --no-fehbg --bg-tile /dev/shm/bg/out.png"); + + + bool found = false; + if(toVisit.size() == 0) { + break; + } + while(found == false) { + if(toVisit.size() == 0) { + break; + } + + found = true; + auto current = toVisit.top(); + toVisit.pop(); + + if(visitedIndices.find(current.v2Index) == visitedIndices.end()) { + auto cIdx = current.v2Index; + visitedIndices.insert(current.v2Index); + explore(cIdx, toVisit, current, g); + + } else if(visitedIndices.find(current.v1Index) == visitedIndices.end()) { + auto cIdx = current.v1Index; + visitedIndices.insert(current.v1Index); + explore(cIdx, toVisit, current, g); + } else { + found = false; + } + + } + + } + + } + +} diff --git a/background/src/utils.cpp b/background/src/utils.cpp @@ -0,0 +1,20 @@ +#include "../headers/utils.hpp" +#include <cstdlib> + +float square(float x) { + return x * x; +} + +// call srand before invocation as this is a pure function. +Vector2 randomPosition(float xMax, float yMax) { + float r1 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) * xMax; + float r2 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) * yMax; + Vector2 v {r1,r2}; + return v; +} + +float distanceSquared(Vector2 v1, Vector2 v2) { + float xSquare = square(v1.x - v2.x); + float ySquare = square(v1.y - v2.y); + return xSquare + ySquare; +} diff --git a/background/src/vertex.cpp b/background/src/vertex.cpp @@ -0,0 +1,21 @@ +#include "../headers/vertex.hpp" +#include <string> +#include <raylib.h> + +Vertex::Vertex(Vector2 position, float drawSize) + : position(position), drawSize(drawSize) {} + + +std::string Vertex::toString() { + std::string result = "(" + std::to_string(this->position.x) + ", " + std::to_string(this->position.y) + ")"; + return result; +} + + +void Vertex::render() { + if(visited) { + DrawCircle(position.x, position.y, drawSize, WHITE); + } else { + DrawCircle(position.x, position.y, drawSize, DARKGRAY); + } +} diff --git a/background/utils.cpp b/background/utils.cpp @@ -1,20 +0,0 @@ -#include "utils.hpp" -#include <cstdlib> - -float square(float x) { - return x * x; -} - -// call srand before invocation as this is a pure function. -Vector2 randomPosition(float xMax, float yMax) { - float r1 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) * xMax; - float r2 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) * yMax; - Vector2 v {r1,r2}; - return v; -} - -float distanceSquared(Vector2 v1, Vector2 v2) { - float xSquare = square(v1.x - v2.x); - float ySquare = square(v1.y - v2.y); - return xSquare + ySquare; -} diff --git a/background/vertex.cpp b/background/vertex.cpp @@ -1,21 +0,0 @@ -#include "vertex.hpp" -#include <string> -#include <raylib.h> - -Vertex::Vertex(Vector2 position, float drawSize) - : position(position), drawSize(drawSize) {} - - -std::string Vertex::toString() { - std::string result = "(" + std::to_string(this->position.x) + ", " + std::to_string(this->position.y) + ")"; - return result; -} - - -void Vertex::render() { - if(visited) { - DrawCircle(position.x, position.y, drawSize, WHITE); - } else { - DrawCircle(position.x, position.y, drawSize, DARKGRAY); - } -}