figments: docs++
This commit is contained in:
parent
3eb145ba00
commit
e837232872
@ -3,13 +3,38 @@
|
|||||||
|
|
||||||
#include "Geometry.h"
|
#include "Geometry.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic interface for converting between virtual and physical coordinates
|
||||||
|
*/
|
||||||
struct CoordinateMapping {
|
struct CoordinateMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps physical coordinates to virtual coordinates.
|
||||||
|
* Virtual coordinates range from 0 to 255. Physical coordinates are
|
||||||
|
* hardware-dependent.
|
||||||
|
*/
|
||||||
virtual VirtualCoordinates physicalToVirtualCoords(const PhysicalCoordinates localCoords) const = 0;
|
virtual VirtualCoordinates physicalToVirtualCoords(const PhysicalCoordinates localCoords) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps virtual coordinates to physical (aka, hardware) coordinates.
|
||||||
|
* Virtual coordinates range from 0 to 255. Physical coordinates are
|
||||||
|
* hardware-dependent.
|
||||||
|
*/
|
||||||
virtual PhysicalCoordinates virtualToPhysicalCoords(const VirtualCoordinates virtualCoords) const = 0;
|
virtual PhysicalCoordinates virtualToPhysicalCoords(const VirtualCoordinates virtualCoords) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the underlying FastLED array, i.e., the physical
|
||||||
|
* hardware pixel.
|
||||||
|
*/
|
||||||
virtual int physicalCoordsToIndex(const PhysicalCoordinates localCoords) const = 0;
|
virtual int physicalCoordsToIndex(const PhysicalCoordinates localCoords) const = 0;
|
||||||
virtual unsigned int physicalPixelCount() const = 0;
|
virtual unsigned int physicalPixelCount() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic mapping for a contiguous 1-d linear display, eg, an LED strip.
|
||||||
|
*
|
||||||
|
* X value ranges from 0 to 255; all Y values are flattened to Y=0
|
||||||
|
*/
|
||||||
struct LinearCoordinateMapping: CoordinateMapping {
|
struct LinearCoordinateMapping: CoordinateMapping {
|
||||||
unsigned int pixelCount = 1;
|
unsigned int pixelCount = 1;
|
||||||
unsigned int startPixel = 0;
|
unsigned int startPixel = 0;
|
||||||
@ -32,22 +57,51 @@ struct LinearCoordinateMapping: CoordinateMapping {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection between the rendering engine and the physical hardware.
|
||||||
|
* Provides direct access to the underlying FastLED array.
|
||||||
|
*/
|
||||||
class Display {
|
class Display {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Display(CRGB* pixels, int pixelCount, const CoordinateMapping* map)
|
Display(CRGB* pixels, int pixelCount, const CoordinateMapping* map)
|
||||||
: m_pixels(pixels), m_pixelCount(pixelCount), m_coordMap(map) {}
|
: m_pixels(pixels), m_pixelCount(pixelCount), m_coordMap(map) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the physical pixel at the given physical coordinates
|
||||||
|
*/
|
||||||
CRGB& pixelAt(const PhysicalCoordinates coords);
|
CRGB& pixelAt(const PhysicalCoordinates coords);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the physical pixel at the given virtual coordinates
|
||||||
|
*/
|
||||||
CRGB& pixelAt(const VirtualCoordinates coords);
|
CRGB& pixelAt(const VirtualCoordinates coords);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the physical pixel in the underlying FastLED array
|
||||||
|
*/
|
||||||
CRGB& pixelAt(int idx);
|
CRGB& pixelAt(int idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how many pixels are in this display
|
||||||
|
*/
|
||||||
int pixelCount() const;
|
int pixelCount() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw underlying FastLED array
|
||||||
|
*/
|
||||||
CRGB* pixelBacking() const;
|
CRGB* pixelBacking() const;
|
||||||
const CoordinateMapping* coordinateMapping() const;
|
const CoordinateMapping* coordinateMapping() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets every pixel to (0, 0, 0)
|
||||||
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets every pixel to the given display
|
||||||
|
*/
|
||||||
void clear(const CRGB& color);
|
void clear(const CRGB& color);
|
||||||
void clear(VirtualCoordinates& start, VirtualCoordinates& end, const CRGB& color);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRGB* m_pixels;
|
CRGB* m_pixels;
|
||||||
|
@ -10,13 +10,36 @@ class Display;
|
|||||||
class InputEvent;
|
class InputEvent;
|
||||||
class InputSource;
|
class InputSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic interface for anything that can be executed and respond to events.
|
||||||
|
*/
|
||||||
struct Loopable {
|
struct Loopable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the MainLoop to process events
|
||||||
|
*/
|
||||||
virtual void handleEvent(const InputEvent& event) {}
|
virtual void handleEvent(const InputEvent& event) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on every MainLoop tick
|
||||||
|
*/
|
||||||
virtual void loop() = 0;
|
virtual void loop() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Loopable that can be named and may be started or stopped in a MainLoop.
|
||||||
|
*/
|
||||||
struct Task : public virtual Loopable {
|
struct Task : public virtual Loopable {
|
||||||
|
/**
|
||||||
|
* Implement in a subclass to run when the task is started
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
virtual void onStart() {};
|
virtual void onStart() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement in a subclass to run when the task is stopped.
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
virtual void onStop() {};
|
virtual void onStop() {};
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
@ -27,27 +50,52 @@ struct Task : public virtual Loopable {
|
|||||||
Task() {}
|
Task() {}
|
||||||
explicit Task(const char* name) : name(name) {}
|
explicit Task(const char* name) : name(name) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the task and makes it schedulable
|
||||||
|
*/
|
||||||
void start() { state = Running; onStart(); }
|
void start() { state = Running; onStart(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the task and makes it unschedulable
|
||||||
|
*/
|
||||||
void stop() { onStop(); state = Stopped; }
|
void stop() { onStop(); state = Stopped; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hacky way to determine if a task is a Figment subclass or not, without
|
||||||
|
* having to resort to RTTI
|
||||||
|
*/
|
||||||
virtual bool isFigment() const { return false; }
|
virtual bool isFigment() const { return false; }
|
||||||
|
|
||||||
const char* name = "";
|
const char* name = "";
|
||||||
State state = Stopped;
|
State state = Stopped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional lambda interface for creating Tasks
|
||||||
|
*/
|
||||||
struct TaskFunc: public Task {
|
struct TaskFunc: public Task {
|
||||||
TaskFunc(std::function<void()> func) : Task("lambda"), func(func) {}
|
TaskFunc(std::function<void()> func) : Task("lambda"), func(func) {}
|
||||||
void loop() override {func();}
|
void loop() override {func();}
|
||||||
std::function<void()> func;
|
std::function<void()> func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Task with a graphical output
|
||||||
|
*/
|
||||||
struct Figment: public Task {
|
struct Figment: public Task {
|
||||||
Figment() : Task() {}
|
Figment() : Task() {}
|
||||||
explicit Figment(const char* name) : Task(name) {}
|
explicit Figment(const char* name) : Task(name) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the Figment should render its output to a display
|
||||||
|
*/
|
||||||
virtual void render(Display* dpy) const = 0;
|
virtual void render(Display* dpy) const = 0;
|
||||||
bool isFigment() const override { return true; }
|
bool isFigment() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional lambda interface for creating Figments
|
||||||
|
*/
|
||||||
struct FigmentFunc: public Figment {
|
struct FigmentFunc: public Figment {
|
||||||
FigmentFunc(std::function<void(Display*)> func) : Figment("lambda"), func(func) {}
|
FigmentFunc(std::function<void(Display*)> func) : Figment("lambda"), func(func) {}
|
||||||
void loop() override {}
|
void loop() override {}
|
||||||
|
@ -1,20 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple ring buffer structure
|
||||||
|
*/
|
||||||
template<typename T, int Size>
|
template<typename T, int Size>
|
||||||
struct Ringbuf {
|
struct Ringbuf {
|
||||||
Ringbuf() : m_head(0), m_tail(0) {}
|
Ringbuf() : m_head(0), m_tail(0) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the buffer's contents
|
||||||
|
*/
|
||||||
void clear() {
|
void clear() {
|
||||||
m_head = 0;
|
m_head = 0;
|
||||||
m_tail = 0;
|
m_tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the next available item, if available
|
||||||
|
*/
|
||||||
T peek(int offset) const {
|
T peek(int offset) const {
|
||||||
const int nextHead = (m_head + offset) % Size;
|
const int nextHead = (m_head + offset) % Size;
|
||||||
return m_items[nextHead];
|
return m_items[nextHead];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and returns the next available item, if any.
|
||||||
|
*
|
||||||
|
* @return false if no data is available, true otherwise
|
||||||
|
*/
|
||||||
bool take(T& dest) {
|
bool take(T& dest) {
|
||||||
if (m_head == m_tail) {
|
if (m_head == m_tail) {
|
||||||
return false;
|
return false;
|
||||||
@ -26,6 +40,10 @@ struct Ringbuf {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item into the buffer. If the buffer is full, the oldest item
|
||||||
|
* is overwritten.
|
||||||
|
*/
|
||||||
void insert(const T& src) {
|
void insert(const T& src) {
|
||||||
const int cur = m_tail;
|
const int cur = m_tail;
|
||||||
const int nextTail = (m_tail + 1) % Size;
|
const int nextTail = (m_tail + 1) % Size;
|
||||||
@ -37,6 +55,9 @@ struct Ringbuf {
|
|||||||
m_items[cur] = src;
|
m_items[cur] = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes the entire buffer and writes it to the given array.
|
||||||
|
*/
|
||||||
size_t write(T(&dest)[Size]) {
|
size_t write(T(&dest)[Size]) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
@ -47,6 +68,9 @@ struct Ringbuf {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes the entire buffer and writes it to the given output
|
||||||
|
*/
|
||||||
size_t write(Print& stream) {
|
size_t write(Print& stream) {
|
||||||
T val;
|
T val;
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
@ -56,6 +80,9 @@ struct Ringbuf {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how many items are available in the buffer
|
||||||
|
*/
|
||||||
size_t size() {
|
size_t size() {
|
||||||
if (m_tail > m_head) {
|
if (m_tail > m_head) {
|
||||||
return m_tail - m_head;
|
return m_tail - m_head;
|
||||||
|
@ -6,13 +6,34 @@
|
|||||||
|
|
||||||
class Display;
|
class Display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A high performance and hardware-independent rendering surface which
|
||||||
|
* represents a full 2d display ranging from (0,0) to (255, 255), that may be
|
||||||
|
* rotated.
|
||||||
|
*
|
||||||
|
* Simple brushes and complex shaders may be applied to a Surface using
|
||||||
|
* @paintWith and @paintShader. The Surface will only execute each shader or
|
||||||
|
* brush once for each physical pixel in the display, allowing you to design
|
||||||
|
* display-independent graphics.
|
||||||
|
*/
|
||||||
class Surface {
|
class Surface {
|
||||||
public:
|
public:
|
||||||
Surface(Display* dpy, const VirtualCoordinates& start, const VirtualCoordinates& end);
|
Surface(Display* dpy, const VirtualCoordinates& start, const VirtualCoordinates& end);
|
||||||
Surface(Display* dpy, const VirtualCoordinates& start, const VirtualCoordinates& end, uint8_t rotation);
|
Surface(Display* dpy, const VirtualCoordinates& start, const VirtualCoordinates& end, uint8_t rotation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the entire surface to one solid color
|
||||||
|
*/
|
||||||
Surface& operator=(const CRGB& color);
|
Surface& operator=(const CRGB& color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given color to every pixel on the surface
|
||||||
|
*/
|
||||||
Surface& operator+=(const CRGB& color);
|
Surface& operator+=(const CRGB& color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OR operation that applies the given color to every pixel on the surface
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Surface& operator|=(const T& val) {
|
Surface& operator|=(const T& val) {
|
||||||
paintWith([&](CRGB& pixel) {
|
paintWith([&](CRGB& pixel) {
|
||||||
@ -21,10 +42,26 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A lambda function that maps coordinates to colors.
|
||||||
|
*/
|
||||||
using Shader = std::function<void(CRGB&, const VirtualCoordinates& virtPos, const PhysicalCoordinates& realPos, const VirtualCoordinates& surfacePos)>;
|
using Shader = std::function<void(CRGB&, const VirtualCoordinates& virtPos, const PhysicalCoordinates& realPos, const VirtualCoordinates& surfacePos)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple lambda that is called for every pixel in a surface. Commonly
|
||||||
|
* used for solid fills; if you want to map pixel coordinates to colors or
|
||||||
|
* textures, you probably want to use a Shader instead.
|
||||||
|
*/
|
||||||
using BrushFunc = std::function<void(CRGB&)>;
|
using BrushFunc = std::function<void(CRGB&)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given BrushFunc to every physical pixel in the surface
|
||||||
|
*/
|
||||||
void paintWith(BrushFunc func);
|
void paintWith(BrushFunc func);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given Shader to every physical pixel in the surface
|
||||||
|
*/
|
||||||
void paintShader(Shader shader);
|
void paintShader(Shader shader);
|
||||||
|
|
||||||
const PhysicalCoordinates start;
|
const PhysicalCoordinates start;
|
||||||
|
Loading…
Reference in New Issue
Block a user