Skip to content

Commit

Permalink
Merge remote-tracking branch 'Brandon502/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ewoudwijma committed Aug 18, 2024
2 parents 6f57cc2 + b4439aa commit a91f1a5
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 5 deletions.
48 changes: 47 additions & 1 deletion src/App/LedEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ class OctopusEffect: public Effect {
const uint8_t C_Y = leds.size.y / 2 + (offsetY - 128)*leds.size.y/255;
for (pos.x = 0; pos.x < leds.size.x; pos.x++) {
for (pos.y = 0; pos.y < leds.size.y; pos.y++) {
uint16_t indexV = leds.XYZ(pos);
uint16_t indexV = leds.XYZUnprojected(pos);
if (indexV < leds.size.x * leds.size.y) { //excluding UINT16_MAX from XY if out of bounds due to projection
rMap[indexV].angle = 40.7436f * atan2f(pos.y - C_Y, pos.x - C_X); // avoid 128*atan2()/PI
rMap[indexV].radius = hypotf(pos.x - C_X, pos.y - C_Y) * mapp; //thanks Sutaburosu
Expand Down Expand Up @@ -2823,6 +2823,52 @@ class PixelMapEffect: public Effect {
}
}; // PixelMap

class MarioTestEffect: public Effect {
const char * name() {return "MarioTest";}
uint8_t dim() {return _2D;}
const char * tags() {return "💫";}

void loop(LedsLayer &leds) {
bool background = leds.effectData.read<bool>();
uint8_t offsetX = leds.effectData.read<uint8_t>();
uint8_t offsetY = leds.effectData.read<uint8_t>();

const uint8_t mario[16][16] = {
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 2, 2, 2, 3, 3, 4, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 2, 3, 2, 3, 3, 3, 4, 3, 3, 3, 0, 0, 0},
{0, 0, 0, 2, 3, 2, 2, 3, 3, 3, 4, 3, 3, 3, 0, 0},
{0, 0, 0, 0, 2, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 0},
{0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 5, 5, 1, 5, 5, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 5, 5, 5, 1, 5, 5, 1, 5, 5, 5, 0, 0, 0},
{0, 0, 5, 5, 5, 5, 1, 5, 5, 1, 5, 5, 5, 5, 0, 0},
{0, 0, 3, 3, 5, 5, 1, 1, 1, 1, 5, 5, 3, 3, 0, 0},
{0, 0, 3, 3, 3, 1, 6, 1, 1, 6, 1, 3, 3, 3, 0, 0},
{0, 0, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0}
};

CRGB colors[7] = {CRGB::DimGrey, CRGB::Red, CRGB::Brown, CRGB::Tan, CRGB::Black, CRGB::Blue, CRGB::Yellow};

if (background) leds.fill_solid(CRGB::DimGrey);
else leds.fill_solid(CRGB::Black);
//draw 16x16 mario
for (int x = 0; x < 16; x++) for (int y = 0; y < 16; y++) {
leds[Coord3D({x + offsetX, y + offsetY, 0})] = colors[mario[y][x]];
}
}

void controls(LedsLayer &leds, JsonObject parentVar) {
ui->initCheckBox(parentVar, "Background", leds.effectData.write<bool>(false));
ui->initSlider(parentVar, "OffsetX", leds.effectData.write<uint8_t>(leds.size.x/2 - 8), 0, leds.size.x - 16);
ui->initSlider(parentVar, "OffsetY", leds.effectData.write<uint8_t>(leds.size.y/2 - 8), 0, leds.size.y - 16);
}
}; // MarioTest

#ifdef STARBASE_USERMOD_LIVE

class LiveScriptEffect: public Effect {
Expand Down
3 changes: 2 additions & 1 deletion src/App/LedLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ enum ProjectionsE
p_Grouping,
p_Spacing,
p_Transpose,
p_Kaleidoscope,
// p_Kaleidoscope,
p_Scrolling,
p_Acceleration,
p_Checkerboard,
p_Rotate,
p_count // keep as last entry
};

Expand Down
4 changes: 3 additions & 1 deletion src/App/LedModEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class LedModEffects:public SysModule {
effects.push_back(new RubiksCubeEffect);
effects.push_back(new SphereMoveEffect);
effects.push_back(new PixelMapEffect);
effects.push_back(new MarioTestEffect);

#ifdef STARBASE_USERMOD_LIVE
effects.push_back(new LiveScriptEffect);
Expand All @@ -136,10 +137,11 @@ class LedModEffects:public SysModule {
fixture.projections.push_back(new GroupingProjection);
fixture.projections.push_back(new SpacingProjection);
fixture.projections.push_back(new TransposeProjection);
fixture.projections.push_back(new KaleidoscopeProjection);
// fixture.projections.push_back(new KaleidoscopeProjection);
fixture.projections.push_back(new ScrollingProjection);
fixture.projections.push_back(new AccelerationProjection);
fixture.projections.push_back(new CheckerboardProjection);
fixture.projections.push_back(new RotateProjection);

#ifdef STARLIGHT_CLOCKLESS_LED_DRIVER
#if !(CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2)
Expand Down
158 changes: 156 additions & 2 deletions src/App/LedProjections.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,22 @@ class TiltPanRollProjection: public Projection {
public:

void setup(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted, Coord3D &mapped, uint16_t &indexV) {
// adjustSizeAndPixel(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted); // Uncomment to expand grid to fill corners
DefaultProjection dp;
dp.setup(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted, mapped, indexV);
}

void adjustSizeAndPixel(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted) {
uint8_t size = max(sizeAdjusted.x, max(sizeAdjusted.y, sizeAdjusted.z));
size = sqrt(size * size * 2) + 1;
Coord3D offset = {(size - sizeAdjusted.x) / 2, (size - sizeAdjusted.y) / 2, 0};
sizeAdjusted = Coord3D{size, size, 1};

pixelAdjusted.x += offset.x;
pixelAdjusted.y += offset.y;
pixelAdjusted.z += offset.z;
}

void adjustXYZ(LedsLayer &leds, Coord3D &pixel) {
#ifdef STARBASE_USERMOD_MPU6050
if (leds.proGyro) {
Expand Down Expand Up @@ -598,7 +610,7 @@ class GroupingProjection: public Projection {
}

void controls(LedsLayer &leds, JsonObject parentVar) {
Coord3D *grouping = leds.projectionData.write<Coord3D>({1,1,1});
Coord3D *grouping = leds.projectionData.write<Coord3D>({2,2,2});
ui->initCoord3D(parentVar, "Grouping", grouping, 0, 100, false, [&leds](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
leds.fixture->layers[rowNr]->triggerMapping();
Expand Down Expand Up @@ -734,7 +746,7 @@ class ScrollingProjection: public Projection {
MirrorProjection mp;
mp.controls(leds, parentVar);

uint8_t *xSpeed = leds.projectionData.write<uint8_t>(0);
uint8_t *xSpeed = leds.projectionData.write<uint8_t>(128);
uint8_t *ySpeed = leds.projectionData.write<uint8_t>(0);
uint8_t *zSpeed = leds.projectionData.write<uint8_t>(0);

Expand Down Expand Up @@ -853,6 +865,148 @@ class CheckerboardProjection: public Projection {
}
}; //CheckerboardProjection

class RotateProjection: public Projection {
const char * name() {return "Rotate";}
const char * tags() {return "💫";}

struct RotateData { // 16 bytes
union {
struct {
bool flip : 1;
bool reverse : 1;
bool alternate : 1;
bool expand : 1;
};
uint8_t flags;
};
uint8_t speed;
uint8_t midX;
uint8_t midY;
uint16_t angle;
uint16_t interval; // ms between updates
int16_t shearX;
int16_t shearY;
unsigned long lastUpdate; // last sys->now update
};

public:

void setup(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted, Coord3D &mapped, uint16_t &indexV) {
adjustSizeAndPixel(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted);
DefaultProjection dp;
dp.setup(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted, mapped, indexV);
}

void adjustSizeAndPixel(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted) {
leds.projectionData.begin();
RotateData *data = leds.projectionData.readWrite<RotateData>();
if (leds.size == Coord3D{0, 0, 0}) {
data->expand = mdl->getValue("Expand");
}
if (data->expand) {
uint8_t size = max(sizeAdjusted.x, max(sizeAdjusted.y, sizeAdjusted.z));
size = sqrt(size * size * 2) + 1;
Coord3D offset = {(size - sizeAdjusted.x) / 2, (size - sizeAdjusted.y) / 2, 0};
sizeAdjusted = Coord3D{size, size, 1};
pixelAdjusted.x += offset.x;
pixelAdjusted.y += offset.y;
pixelAdjusted.z += offset.z;
}
if (leds.size == Coord3D{0, 0, 0}) {
data->midX = sizeAdjusted.x / 2;
data->midY = sizeAdjusted.y / 2;
return;
}
}

void adjustXYZ(LedsLayer &leds, Coord3D &pixel) {
leds.projectionData.begin();
RotateData *data = leds.projectionData.readWrite<RotateData>();

constexpr int Fixed_Scale = 1 << 10;

if ((sys->now - data->lastUpdate > data->interval) && data->speed) { // Only update if the angle has changed
data->lastUpdate = sys->now;
// Increment the angle
data->angle = data->reverse ? (data->angle <= 0 ? 359 : data->angle - 1) : (data->angle >= 359 ? 0 : data->angle + 1);

if (data->alternate && (data->angle == 0)) data->reverse = !data->reverse;

data->flip = (data->angle > 90 && data->angle < 270);

int newAngle = data->angle; // Flip newAngle if needed. Don't change angle in data
if (data->flip) {newAngle += 180; newAngle %= 360;}

// Calculate shearX and shearY
float angleRadians = radians(newAngle);
data->shearX = -tan(angleRadians / 2) * Fixed_Scale;
data->shearY = sin(angleRadians) * Fixed_Scale;
}

int maxX = leds.size.x;
int maxY = leds.size.y;

if (data->flip) {
// Reverse x and y values
pixel.x = maxX - pixel.x;
pixel.y = maxY - pixel.y;
}

// Translate pixel to origin
int dx = pixel.x - data->midX;
int dy = pixel.y - data->midY;

// Apply the 3 shear transformations
int x1 = dx + data->shearX * dy / Fixed_Scale;
int y1 = dy + data->shearY * x1 / Fixed_Scale;
int x2 = x1 + data->shearX * y1 / Fixed_Scale;

// Translate pixel back and assign
pixel.x = x2 + data->midX;
pixel.y = y1 + data->midY;
pixel.z = 0;

// Clamp the pixel to the bounds
if (pixel.x < 0) pixel.x = 0;
else if (pixel.x >= maxX) pixel.x = maxX - 1;
if (pixel.y < 0) pixel.y = 0;
else if (pixel.y >= maxY) pixel.y = maxY - 1;
}

void controls(LedsLayer &leds, JsonObject parentVar) {
RotateData *data = leds.projectionData.readWrite<RotateData>();

ui->initSelect(parentVar, "Direction", 0, false, [data](JsonObject var, uint8_t rowNr, uint8_t funType) { switch (funType) { //varFun
case onUI: {
JsonArray options = ui->setOptions(var);
options.add("Clockwise");
options.add("Counter-Clockwise");
options.add("Alternate");
return true; }
case onChange: {
uint8_t val = mdl->getValue(var, rowNr);
if (val == 0) data->reverse = false;
if (val == 1) data->reverse = true;
if (val == 2) data->alternate = true; else data->alternate = false;
return true; }
default: return false;
}});
ui->initSlider(parentVar, "Rotate Speed", 128, 0, 254, false, [data](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
data->speed = mdl->getValue(var, rowNr);
data->interval = 1000 / (data->speed + 1);
return true;
default: return false;
}});
ui->initCheckBox(parentVar, "Expand", false, false, [&leds](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
leds.fixture->layers[rowNr]->triggerMapping();
return true;
default: return false;
}});
}
}; //RotateProjection

class TestProjection: public Projection {
const char * name() {return "Test";}
const char * tags() {return "💡";}
Expand Down

0 comments on commit a91f1a5

Please sign in to comment.