#ifndef PALETTES_PATH Cd(__DIR__);; #include "Load" #endif // FIXME: bug where holding CTRL for 5-ish seconds crashes program! // TODO: move to Demo/Graphics, make sprite link in Menu #define SLIDER_RANGE 255 #define SLIDER_SPACING 28 #define SLIDER_BORDER 2 I64 current_palette = "*New Palette"; I64 selected_color = 0; I64 l, r, t, b; U8 *manual_value; CBGR24 gr_temp_palette[COLORS_NUM]; class CSliderState { I64 left_pos; I64 middle_pos; I64 right_pos; I64 preview; CBGR24 color; } sld; I0 DrawPixel(I64 x, I64 y, CBGR24 color) { text.fb_alias[x + y * GR_WIDTH] = color; } U0 DrawCtrlSlider(CDC *dc, CCtrl *c) { CSliderState *s = c->state; I64 size = (c->win_task->pix_width / 16), size2 = (c->win_task->pix_height / 32), i, pos, col, bias; /////////////////////// // CURRENT SELECTION // /////////////////////// // current color box preview dc->color = BLACK; GrPrint(dc, 10, 10, "Preview:"); GrPrint(dc, 10, 26, "Current Color: #%d", selected_color); if (selected_color == 15) dc->color = LTGRAY; else if (gr_palette[selected_color] > 0xCCCCCC) dc->color = DKGRAY; else dc->color = 15; GrRect(dc, 94, 8, 58, 12); // #Hex value dc->color = selected_color; GrRect(dc, 78, 8, 12, 12); GrPrint(dc, 95, 10, "#%x%x%x", gr_palette[selected_color].r, gr_palette[selected_color].g, gr_palette[selected_color].b); // palette name dc->color = BLACK; GrPrint(dc, 10, 43, "Palette: %s", current_palette); //////////// // SLIDER // //////////// //box dc->color = LTRED; GrRect(dc, c->left, c->top, SLIDER_SPACING * 4 + 2, SLIDER_SPACING * 2 + SLIDER_RANGE); dc->color = BLUE; GrRect(dc, c->left + SLIDER_BORDER, c->top + SLIDER_BORDER, SLIDER_SPACING * 4 + 2 - 2 * SLIDER_BORDER, SLIDER_SPACING * 2 + SLIDER_RANGE - 2 * SLIDER_BORDER); //slider dc->color = BLACK; for (i = 1; i <= 3; i++) { GrLine(dc, c->left + i * SLIDER_SPACING + i - 1, c->top + SLIDER_SPACING, c->left + i * SLIDER_SPACING + i - 1, c->top + SLIDER_SPACING + SLIDER_RANGE - 1); } //values dc->color = LTRED; for (i = 1; i <= 3; i++) { switch (i) { case 1: pos = s->left_pos; col = "R"; break; case 2: pos = s->middle_pos; col = "G"; break; case 3: pos = s->right_pos; col = "B"; break; } //values GrPrint(dc, c->left + i * SLIDER_SPACING + i - FONT_WIDTH / 2, c->top + SLIDER_SPACING + SLIDER_RANGE + 8, "%d", pos); //RGB label GrPrint(dc, c->left + i * SLIDER_SPACING + 3 - FONT_WIDTH / 2, c->top + 14, "%s", col); //knobs GrRect(dc, c->left + i * SLIDER_SPACING + i - 4, c->top + SLIDER_SPACING + SLIDER_RANGE - 1 - pos - 2, 7, 5); } //////////////////// // COLORS PREVIEW // //////////////////// dc->color = 8; GrRect(dc, 0, c->win_task->pix_height + size * 1.5 - size * 2, c->win_task->pix_width, size * 0.75); for (i = 0; i < COLORS_NUM; i++) { // color label and text preview // TODO: THIS LOGIC DOESNT WORK ON LIGHT THEMES // if color too light or too dark add bg if (i == 15) dc->color = LTGRAY; else if (gr_palette[i] < gr_palette[15]) dc->color = LTGRAY; else if (gr_palette[i] > gr_palette[0]) dc->color = DKGRAY; /*else if (i == 7) dc->color = LTRED;*/ else dc->color = 15; if (i == selected_color) dc->color = 0; GrRect(dc, 6, (size2 * 2) + 65 + 16 * i, 80, 18); GrRect(dc, (size * i), c->win_task->pix_height - (size - size / 2), size, size * 1.5); GrRect(dc, 6, (size2 * 2) + 65 + 16 * i, 80, 18); if (i == selected_color) dc->color = 15; else dc->color = i; bias = (size / 2) - 4; if (i >= 9) bias = (size / 2) - 8; GrPrint(dc, bias + (i * size), c->win_task->pix_height - (size * .6) + (size / 4), "%d", i); GrPrint(dc, 10, (size2 * 2) + 70 + 16 * i, "#%d: Test", i); // Border for preview box GrRect(dc, (size * i)-2, c->win_task->pix_height - (size*1.5)-1, size+2, size+1); // preview box dc->color = i; GrRect(dc, (size * i), c->win_task->pix_height - (size*1.5), size, size); } // Add Save/Load button? } U0 PESave(Bool prompt, CCtrl *c) { CDoc *doc = DocNew(PALETTES_PATH); I64 i; no_warn c; // TODO remove param if not needed U8 *tmp1, *tmp2; // 1: lower, 2: Capital if (prompt) DocForm(&doc->filename); tmp1 = StrNew(&doc->filename.name); StrLastRemove(tmp1, "/", tmp1); StrReplace(tmp1, ".ZC", ""); for (i = 0; i < StrLen(tmp1); i++) if ('A' <= tmp1[i] <= 'Z') tmp1[i] = tmp1[i] + 32; tmp2 = StrNew(tmp1); tmp2[0] = ToUpper(tmp2[0]); DocPrint(doc, "public CBGR24 gr_palette_%s[COLORS_NUM] = {\n", tmp1); for (i = 0; i < COLORS_NUM; i++) { if (i == COLORS_NUM - 1) DocPrint(doc, "0x%X", gr_palette[i]); else DocPrint(doc, "0x%X, ", gr_palette[i]); } DocPrint(doc, "\n};\npublic U0 PaletteSet%s(Bool persistent=TRUE)\n{\n" "\tGrPaletteSet(gr_palette_%s);\n" "\tLFBFlush;\n" "\tif (persistent)\n" "\t\tfp_set_std_palette = &PaletteSet%s;\n}", tmp2, tmp1, tmp2); DocWrite(doc); DocDel(doc); } U0 PaletteSetTemp(Bool persistent=TRUE) {//Activate temp palette. GrPaletteSet(gr_palette); LFBFlush; if (persistent) fp_set_std_palette = &PaletteSetTemp; } U0 PalettePrint(){ I64 i; for (i = 0; i < COLORS_NUM; i++) { "%d: #%X\n", i, gr_palette[i]; } } U0 SelectColor(I64 color_number, CCtrl *c) { selected_color = color_number; CSliderState *s = c->state; s->left_pos = gr_palette[selected_color].r; s->middle_pos= gr_palette[selected_color].g; s->right_pos = gr_palette[selected_color].b; } U0 UpdateDerivedCtrlSlider(CCtrl *c) { CSliderState *s = c->state; c->left = (c->win_task->pix_width / 2) - (SLIDER_SPACING * 3 + 2) / 2; c->right = c->left + 3 * SLIDER_SPACING + 2; c->top = c->win_task->pix_height / 2 - (SLIDER_SPACING * 2 + SLIDER_RANGE) / 2; c->bottom = c->top + SLIDER_SPACING * 2 + SLIDER_RANGE; // I used to clamp between 0 and 127 and do math but i changed it to 256 for now. s->left_pos = ClampI64(s->left_pos, 0, SLIDER_RANGE); s->middle_pos = ClampI64(s->middle_pos, 0, SLIDER_RANGE); s->right_pos = ClampI64(s->right_pos, 0, SLIDER_RANGE); // add the slider's RGB value to s->preview // opposite for BGR s->preview = s->right_pos + s->middle_pos << 8 + s->left_pos << 16; //s->left_pos + s->middle_pos << 8 + s->right_pos << 16; // cheap way to force redraw 32bit colors // TODO: make this not stupid // can I use *last_task? if (c->win_task->pix_left != l || c->win_task->pix_right != r || c->win_task->pix_bottom != b || c->win_task->pix_top != t) { l = c->win_task->pix_left; r = c->win_task->pix_right; t = c->win_task->pix_top; b = c->win_task->pix_bottom; LFBFlush; } } U0 LeftClickSlider(CCtrl *c, I64 x, I64 y, Bool) { CSliderState *s = c->state; if (x < c->left + 1 * SLIDER_SPACING + 0 + SLIDER_SPACING / 3) s->left_pos = SLIDER_RANGE - 1 - (y - (c->top + SLIDER_SPACING)); else if (x < c->left + 2 * SLIDER_SPACING + 1 + SLIDER_SPACING / 3) s->middle_pos = SLIDER_RANGE - 1 - (y - (c->top + SLIDER_SPACING)); else s->right_pos = SLIDER_RANGE - 1 - (y - (c->top + SLIDER_SPACING)); if (c->update_derived_vals) (*c->update_derived_vals)(c); // set palette gr_palette[selected_color] = s->preview; PaletteSetTemp(FALSE); current_palette = "*New Palette"; } CCtrl *SliderNew() { CCtrl *c = CAlloc(sizeof(CCtrl)); c->win_task = Fs; c->flags = CTRLF_SHOW | CTRLF_CAPTURE_LEFT_MS; c->type = CTRLT_GENERIC; c->state = &sld; MemSet(&sld,0,sizeof(CSliderState)); c->draw_it = &DrawCtrlSlider; c->left_click = &LeftClickSlider; c->update_derived_vals = &UpdateDerivedCtrlSlider; QueueInsert(c, Fs->last_ctrl); TaskDerivedValsUpdate; return c; } U0 SliderDel(CCtrl *c) { QueueRemove(c); Free(c); } public U0 PaletteEditor() { SettingsPush; MenuPush( "File {" " Open(,CH_CTRLO);" " SaveAs(,CH_CTRLA);" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Edit {" " Hex(,'#');" " PreviousColor(,,SC_CURSOR_LEFT);" " PreviousColor(,,SC_CURSOR_UP);" " NextColor(,,SC_CURSOR_RIGHT);" " NextColor(,,SC_CURSOR_DOWN);" " RandomColor(,'r');" " RandomPalette(,'R');" "}" "About {" " Info(,CH_CTRLI);" "}" ); DocClear; DocCursor(OFF); WinBorder(ON); CCtrl *c = SliderNew; I64 /*arg1, arg2,*/ sc = 0, original_left, original_right, original_top, original_bottom; Bool is_done = FALSE, keep_palette = FALSE; original_left = c->win_task->win_left; original_right = c->win_task->win_right; original_top = c->win_task->win_top; original_bottom = c->win_task->win_bottom; // windowed c->win_task->win_left = (GR_WIDTH / 23); c->win_task->win_right = (GR_WIDTH / 13); c->win_task->win_top = GR_HEIGHT / 80; c->win_task->win_bottom = GR_HEIGHT / 10; // init pos for 32bit redraw l = c->win_task->pix_left; r = c->win_task->pix_right; t = c->win_task->pix_top; b = c->win_task->pix_bottom; SelectColor(0, c); try { while (!is_done) { switch (KeyGet(&sc)) { case '#': manual_value = StrGet(" Hex Value: #"); gr_palette[selected_color] = Str2I64(manual_value, 16); Free(manual_value); SelectColor(selected_color, c); LFBFlush; DocClear; break; case 0: switch (sc.u8[0]) { case SC_CURSOR_UP: case SC_CURSOR_LEFT: if (selected_color == 0) selected_color = 16; SelectColor(selected_color - 1, c); break; case SC_CURSOR_DOWN: case SC_CURSOR_RIGHT: if (selected_color == 15) selected_color = -1; SelectColor(selected_color + 1, c); break; } break; case CH_CTRLO: current_palette = ""; current_palette = PaletteSelect; break; case 'r': gr_palette[selected_color] = ColorGod; LFBFlush; break; case 'R': PaletteGod; break; case CH_CTRLI: PopUpOk("\n\n Use the arrows to select color\n\n # to manually input hex value","\n\n\n\t\tMade by y4my4m\n\n"); break; case CH_CTRLA: PESave(TRUE, c); break; case CH_ESC: MemCopy(&gr_temp_palette, gr_palette, sizeof(CBGR24) * COLORS_NUM); keep_palette = TRUE; case CH_SHIFT_ESC: LFBFlush; DocClear; is_done = TRUE; } Refresh; } } catch PutExcept; MenuPop; SettingsPop; if (keep_palette) GrPaletteSet(gr_temp_palette); SliderDel(c); DocBottom; c->win_task->win_left = original_left; c->win_task->win_right = original_right; c->win_task->win_top = original_top; c->win_task->win_bottom = original_bottom; }