feat: Allow -C to specify multi-color, custom palette - #200
Conversation
| if (num_colors > 0 && color_array != NULL) { | ||
| // Rainbow mode with custom color palette | ||
| mcolor = color_array[rand() % num_colors]; |
There was a problem hiding this comment.
Rainbow Mode - Render
When in rainbow mode AND there's a custom color palette, colors are randomly picked from that palette instead of the default 6 colors.
| } else if (num_colors > 0) { | ||
| // Multi-color mode - use stored character colors | ||
| mcolor = matrix[i][j].color; |
There was a problem hiding this comment.
Multi-Color Mode - Render
A color was assigned to the character when it entered the matrix; just use it.
| case '+': | ||
| rainbow = 0; | ||
| if (original_num_colors > 0) { | ||
| num_colors = original_num_colors; // Restore multi-color mode | ||
| } | ||
| break; |
There was a problem hiding this comment.
shift + + will switch into non-rainbow multi-color mode.
| /* Parse each color */ | ||
| char *token = strtok(colors_copy, ","); | ||
| while (token != NULL) { | ||
| int color = parse_color(token); | ||
| if (color == -1) { | ||
| free(colors_copy); | ||
| c_die(" Invalid color selection '%s'\n Valid " | ||
| "colors are green, red, blue, " | ||
| "white, yellow, cyan, magenta and black.\n", token); | ||
| } | ||
| color_array[num_colors++] = color; | ||
| token = strtok(NULL, ","); |
There was a problem hiding this comment.
Multi-Color - Init
We don't deduplicate the colors when parsing, so -C red,red,blue will result in 2x as much red as blue. This is on purpose to allow more nuanced color mixes.
| /** | ||
| * Selects a color for a matrix character based on current global program state. | ||
| * | ||
| * This function uses GLOBAL STATE variables: | ||
| * - num_colors: Number of colors in the custom palette | ||
| * - color_array: Array of custom color values | ||
| * - rainbow: Flag indicating if rainbow mode is active | ||
| * - mcolor: Current default color | ||
| * | ||
| * @return The selected color value (COLOR_* constant) | ||
| */ | ||
| int select_matrix_color(void) { | ||
| if (num_colors > 0 && color_array != NULL && !rainbow) { | ||
| /* Multi-color mode - select from custom palette */ | ||
| return color_array[rand() % num_colors]; | ||
| } else { | ||
| /* Single color mode or no custom palette - use global color */ | ||
| return mcolor; | ||
| } | ||
| } |
There was a problem hiding this comment.
DRY
This specific code was repeated a lot; made it its own function to reduce total lines of code & opportunity for error.
| int mcolor = COLOR_GREEN; | ||
| int rainbow = 0; |
There was a problem hiding this comment.
These were hoisted to global:
mcolorbecause we need to initialize a color invar_init(), and it made sense to use "the current default color" to do so - but in order to do so,mcolorcouldn't be local tomain().rainbowto allow theselect_matrix_colorfunction to be global.
| int mcolor = COLOR_GREEN; /* Current matrix color */ | ||
| int rainbow = 0; /* Flag for rainbow mode */ |
There was a problem hiding this comment.
These were hoisted out of main(); see https://github.com/abishekvashok/cmatrix/pull/200/files#r2072735532
| /* Parse a color name and return the corresponding COLOR_* constant */ | ||
| int parse_color(const char* color_name) { | ||
| if (!strcasecmp(color_name, "green")) { | ||
| return COLOR_GREEN; | ||
| } else if (!strcasecmp(color_name, "red")) { | ||
| return COLOR_RED; | ||
| } else if (!strcasecmp(color_name, "blue")) { | ||
| return COLOR_BLUE; | ||
| } else if (!strcasecmp(color_name, "white")) { | ||
| return COLOR_WHITE; | ||
| } else if (!strcasecmp(color_name, "yellow")) { | ||
| return COLOR_YELLOW; | ||
| } else if (!strcasecmp(color_name, "cyan")) { | ||
| return COLOR_CYAN; | ||
| } else if (!strcasecmp(color_name, "magenta")) { | ||
| return COLOR_MAGENTA; | ||
| } else if (!strcasecmp(color_name, "black")) { | ||
| return COLOR_BLACK; | ||
| } else { | ||
| return -1; /* Invalid color */ | ||
| } | ||
| } |
There was a problem hiding this comment.
We needed to parse colors in two places, so this big if/else was pulled out into its own function.
-C color[,color[,color ...]]Allow the
-Cflag for color selection to specify multi-color palettes.e.g.
cmatrix -C red,white,bluecmatrix -C white,white,white,greenrainbow
-r(rainbow), the rainbow will be taken from the provided color palette instead of the full spectrum.-r, each character will be randomly assigned a color from the palette when it first appears on-screen.key shortcuts
At runtime, key combo
shift++will switch to multi-color mode, if another key combo shifted out of it.compatibility
cmatrix -C red, etc, is unchanged.-r(rainbow) is unchanged if no palette is specified.example
cmatrix.color.mix.demo.mp4