125 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * The LED effects influenced by dice rolls.
 | |
|  */
 | |
| #pragma once
 | |
| 
 | |
| #include "wled.h"
 | |
| 
 | |
| #include "dice_state.h"
 | |
| 
 | |
| // Reuse FX display functions.
 | |
| extern uint16_t mode_breath();
 | |
| extern uint16_t mode_blends();
 | |
| extern uint16_t mode_glitter();
 | |
| extern uint16_t mode_gravcenter();
 | |
| 
 | |
| static constexpr uint8_t USER_ANY_DIE = 0xFF;
 | |
| /**
 | |
|  * Two custom effect parameters are used.
 | |
|  * c1 - Source Die. Sets which die from [0 - MAX_NUM_DICE) controls this effect.
 | |
|  *      If this is set to 0xFF, use the latest event regardless of which die it
 | |
|  *      came from.
 | |
|  * c2 - Target Roll. Sets the "success" criteria for a roll to >= this value.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Return the last die roll based on the custom1 effect setting.
 | |
|  */
 | |
| static pixels::RollEvent GetLastRollForSegment() {
 | |
|   // If an invalid die is selected, fallback to using the most recent roll from
 | |
|   // any die.
 | |
|   if (SEGMENT.custom1 >= MAX_NUM_DICE) {
 | |
|     return GetLastRoll();
 | |
|   } else {
 | |
|     return last_die_events[SEGMENT.custom1];
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Alternating pixels running function (copied static function).
 | |
|  */
 | |
| // paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
 | |
| #define PALETTE_SOLID_WRAP   (strip.paletteBlend == 1 || strip.paletteBlend == 3)
 | |
| static uint16_t running_copy(uint32_t color1, uint32_t color2, bool theatre = false) {
 | |
|   int width = (theatre ? 3 : 1) + (SEGMENT.intensity >> 4);  // window
 | |
|   uint32_t cycleTime = 50 + (255 - SEGMENT.speed);
 | |
|   uint32_t it = strip.now / cycleTime;
 | |
|   bool usePalette = color1 == SEGCOLOR(0);
 | |
| 
 | |
|   for (int i = 0; i < SEGLEN; i++) {
 | |
|     uint32_t col = color2;
 | |
|     if (usePalette) color1 = SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0);
 | |
|     if (theatre) {
 | |
|       if ((i % width) == SEGENV.aux0) col = color1;
 | |
|     } else {
 | |
|       int pos = (i % (width<<1));
 | |
|       if ((pos < SEGENV.aux0-width) || ((pos >= SEGENV.aux0) && (pos < SEGENV.aux0+width))) col = color1;
 | |
|     }
 | |
|     SEGMENT.setPixelColor(i,col);
 | |
|   }
 | |
| 
 | |
|   if (it != SEGENV.step) {
 | |
|     SEGENV.aux0 = (SEGENV.aux0 +1) % (theatre ? width : (width<<1));
 | |
|     SEGENV.step = it;
 | |
|   }
 | |
|   return FRAMETIME;
 | |
| }
 | |
| 
 | |
| static uint16_t simple_roll() {
 | |
|   auto roll = GetLastRollForSegment();
 | |
|   if (roll.state != pixels::RollState::ON_FACE) {
 | |
|     SEGMENT.fill(0);
 | |
|   } else {
 | |
|     uint16_t num_segments = float(roll.current_face + 1) / 20.0 * SEGLEN;
 | |
|     for (int i = 0; i <= num_segments; i++) {
 | |
|       SEGMENT.setPixelColor(i, SEGCOLOR(0));
 | |
|     }
 | |
|     for (int i = num_segments; i < SEGLEN; i++) {
 | |
|       SEGMENT.setPixelColor(i, SEGCOLOR(1));
 | |
|     }
 | |
|   }
 | |
|   return FRAMETIME;
 | |
| }
 | |
| // See https://kno.wled.ge/interfaces/json-api/#effect-metadata
 | |
| // Name - DieSimple
 | |
| // Parameters -
 | |
| //   * Selected Die (custom1)
 | |
| // Colors - Uses color1 and color2
 | |
| // Palette - Not used
 | |
| // Flags - Effect is optimized for use on 1D LED strips.
 | |
| // Defaults - Selected Die set to 0xFF (USER_ANY_DIE)
 | |
| static const char _data_FX_MODE_SIMPLE_DIE[] PROGMEM =
 | |
|     "DieSimple@,,Selected Die;!,!;;1;c1=255";
 | |
| 
 | |
| static uint16_t pulse_roll() {
 | |
|   auto roll = GetLastRollForSegment();
 | |
|   if (roll.state != pixels::RollState::ON_FACE) {
 | |
|     return mode_breath();
 | |
|   } else {
 | |
|     uint16_t ret = mode_blends();
 | |
|     uint16_t num_segments = float(roll.current_face + 1) / 20.0 * SEGLEN;
 | |
|     for (int i = num_segments; i < SEGLEN; i++) {
 | |
|       SEGMENT.setPixelColor(i, SEGCOLOR(1));
 | |
|     }
 | |
|     return ret;
 | |
|   }
 | |
| }
 | |
| static const char _data_FX_MODE_PULSE_DIE[] PROGMEM =
 | |
|     "DiePulse@!,!,Selected Die;!,!;!;1;sx=24,pal=50,c1=255";
 | |
| 
 | |
| static uint16_t check_roll() {
 | |
|   auto roll = GetLastRollForSegment();
 | |
|   if (roll.state != pixels::RollState::ON_FACE) {
 | |
|     return running_copy(SEGCOLOR(0), SEGCOLOR(2));
 | |
|   } else {
 | |
|     if (roll.current_face + 1 >= SEGMENT.custom2) {
 | |
|       return mode_glitter();
 | |
|     } else {
 | |
|       return mode_gravcenter();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| static const char _data_FX_MODE_CHECK_DIE[] PROGMEM =
 | |
|     "DieCheck@!,!,Selected Die,Target Roll;1,2,3;!;1;pal=0,ix=128,m12=2,si=0,c1=255,c2=10";
 | 
