@@ -134,6 +134,15 @@ struct Trigs128 : Module, QuantizeUtils {
134134 LIFE_RATE_X16 ,
135135 NUM_LIFE_RATE_MODES
136136 };
137+ enum GridShadeMode {
138+ GS_PROBABILITY ,
139+ GS_PITCH ,
140+ GS_CV ,
141+ GS_CV2 ,
142+ GS_RATCHETS ,
143+ GS_DIVISION ,
144+ NUM_GRID_SHADE_MODES
145+ };
137146
138147 std::array<CellProps, GRID_CELLS > cells;
139148 int selectedX = 0 ;
@@ -174,6 +183,7 @@ struct Trigs128 : Module, QuantizeUtils {
174183 bool polyphonicFirstRowOutputs = false ;
175184 int cvRangeMode = CV_RANGE_BIPOLAR_10V ;
176185 int cv2RangeMode = CV_RANGE_BIPOLAR_10V ;
186+ int gridShadeMode = GS_PROBABILITY ;
177187 int lifeRateMode = LIFE_RATE_X1 ;
178188 int lifeClockCounter = 0 ;
179189 bool lifeStationaryLatched = false ;
@@ -315,6 +325,43 @@ struct Trigs128 : Module, QuantizeUtils {
315325 selectedDirty = true ;
316326 }
317327
328+ static const char *getGridShadeLabel (int mode) {
329+ switch (clampijw (mode, 0 , NUM_GRID_SHADE_MODES - 1 )) {
330+ case GS_PROBABILITY : return " Probability" ;
331+ case GS_PITCH : return " Pitch" ;
332+ case GS_CV : return " CV" ;
333+ case GS_CV2 : return " CV2" ;
334+ case GS_RATCHETS : return " Ratchets" ;
335+ case GS_DIVISION : return " Division" ;
336+ default : return " Probability" ;
337+ }
338+ }
339+
340+ float getGridShadeNorm (const CellProps &c) const {
341+ switch (clampijw (gridShadeMode, 0 , NUM_GRID_SHADE_MODES - 1 )) {
342+ case GS_PROBABILITY :
343+ return clampfjw (c.probability , 0 .f , 1 .f );
344+ case GS_PITCH :
345+ return clampfjw (c.pitch / 10 .f , 0 .f , 1 .f );
346+ case GS_CV : {
347+ CvRangeSpec spec = getCvRangeSpec (cvRangeMode);
348+ float denom = std::max (0 .0001f , spec.max - spec.min );
349+ return clampfjw ((c.cv - spec.min ) / denom, 0 .f , 1 .f );
350+ }
351+ case GS_CV2 : {
352+ CvRangeSpec spec = getCvRangeSpec (cv2RangeMode);
353+ float denom = std::max (0 .0001f , spec.max - spec.min );
354+ return clampfjw ((c.cv2 - spec.min ) / denom, 0 .f , 1 .f );
355+ }
356+ case GS_RATCHETS :
357+ return clampfjw ((float )(c.ratchets - 1 ) / 7 .f , 0 .f , 1 .f );
358+ case GS_DIVISION :
359+ return clampfjw ((float )(c.division - 1 ) / 15 .f , 0 .f , 1 .f );
360+ default :
361+ return clampfjw (c.probability , 0 .f , 1 .f );
362+ }
363+ }
364+
318365 void invalidateLifeStationaryState () {
319366 lifeStationaryLatched = false ;
320367 lifePrevActiveValid = false ;
@@ -484,6 +531,7 @@ struct Trigs128 : Module, QuantizeUtils {
484531 json_object_set_new (rootJ, " polyphonicFirstRowOutputs" , json_boolean (polyphonicFirstRowOutputs));
485532 json_object_set_new (rootJ, " cvRangeMode" , json_integer (cvRangeMode));
486533 json_object_set_new (rootJ, " cv2RangeMode" , json_integer (cv2RangeMode));
534+ json_object_set_new (rootJ, " gridShadeMode" , json_integer (gridShadeMode));
487535 json_object_set_new (rootJ, " lifeEnabled" , json_boolean (params[LIFE_ON_SWITCH_PARAM ].getValue () > 0 .5f ));
488536 json_object_set_new (rootJ, " lifeRateMode" , json_integer (lifeRateMode));
489537 return rootJ;
@@ -525,6 +573,8 @@ struct Trigs128 : Module, QuantizeUtils {
525573 if (cvRangeJ) cvRangeMode = clampijw ((int )json_integer_value (cvRangeJ), 0 , NUM_CV_RANGE_MODES - 1 );
526574 json_t *cv2RangeJ = json_object_get (rootJ, " cv2RangeMode" );
527575 if (cv2RangeJ) cv2RangeMode = clampijw ((int )json_integer_value (cv2RangeJ), 0 , NUM_CV_RANGE_MODES - 1 );
576+ json_t *gridShadeJ = json_object_get (rootJ, " gridShadeMode" );
577+ if (gridShadeJ) gridShadeMode = clampijw ((int )json_integer_value (gridShadeJ), 0 , NUM_GRID_SHADE_MODES - 1 );
528578 json_t *lifeEnabledJ = json_object_get (rootJ, " lifeEnabled" );
529579 if (lifeEnabledJ) params[LIFE_ON_SWITCH_PARAM ].setValue (json_boolean_value (lifeEnabledJ) ? 1 .f : 0 .f );
530580 json_t *lifeRateModeJ = json_object_get (rootJ, " lifeRateMode" );
@@ -1302,7 +1352,8 @@ struct Trigs128Display : LightWidget {
13021352 if (c.active ) {
13031353 int track = clampijw (y / 4 , 0 , 3 );
13041354 NVGcolor color = trackColors[track];
1305- color.a = clampfjw (0 .35f + (c.probability * 0 .65f ), 0 .f , 1 .f );
1355+ float shade = module ->getGridShadeNorm (c);
1356+ color.a = clampfjw (0 .35f + (shade * 0 .65f ), 0 .f , 1 .f );
13061357 nvgFillColor (args.vg , color);
13071358 nvgBeginPath (args.vg );
13081359 nvgRect (args.vg , x * cw, y * ch, cw, ch);
@@ -1814,6 +1865,38 @@ struct Trigs128Widget : ModuleWidget {
18141865 }
18151866 };
18161867
1868+ struct GridShadeChoiceItem : MenuItem {
1869+ Trigs128 *module = nullptr ;
1870+ int mode = 0 ;
1871+ void onAction (const event::Action &e) override {
1872+ if (!module ) return ;
1873+ module ->gridShadeMode = clampijw (mode, 0 , Trigs128::NUM_GRID_SHADE_MODES - 1 );
1874+ }
1875+ void step () override {
1876+ rightText = (module && module ->gridShadeMode == mode) ? " ✔" : " " ;
1877+ MenuItem::step ();
1878+ }
1879+ };
1880+
1881+ struct GridShadeMenuItem : MenuItem {
1882+ Trigs128 *module = nullptr ;
1883+ Menu *createChildMenu () override {
1884+ Menu *child = new Menu;
1885+ for (int mode = 0 ; mode < Trigs128::NUM_GRID_SHADE_MODES ; mode++) {
1886+ GridShadeChoiceItem *item = new GridShadeChoiceItem;
1887+ item->module = module ;
1888+ item->mode = mode;
1889+ item->text = Trigs128::getGridShadeLabel (mode);
1890+ child->addChild (item);
1891+ }
1892+ return child;
1893+ }
1894+ void step () override {
1895+ rightText = " ▶" ;
1896+ MenuItem::step ();
1897+ }
1898+ };
1899+
18171900 struct LifeRateQuantity : Quantity {
18181901 Trigs128 *module = nullptr ;
18191902 void setValue (float value) override {
@@ -1929,6 +2012,11 @@ struct Trigs128Widget : ModuleWidget {
19292012 cv2RangeItem->text = " CV2 Range" ;
19302013 menu->addChild (cv2RangeItem);
19312014
2015+ GridShadeMenuItem *gridShadeItem = new GridShadeMenuItem;
2016+ gridShadeItem->module = module ;
2017+ gridShadeItem->text = " Grid Shading" ;
2018+ menu->addChild (gridShadeItem);
2019+
19322020 menu->addChild (new MenuSeparator ());
19332021 ui::Slider *lifeRateSlider = new ui::Slider;
19342022 LifeRateQuantity *lifeRateQuantity = new LifeRateQuantity;
0 commit comments