Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/cvar.h
2025-09-02 14:43:36 +02:00

681 lines
17 KiB
C

int cvar_fti(float f) {
return *((int*)&f);
}
float cvar_itf(int i) {
return *((float*)&i);
}
void cvar_fnc_void(cvar_t *cv, int value) {
;
}
void cvar_fnc_bool(cvar_t *cv, int value) {
*((byte*)cv->data) = (byte)value;
}
void cvar_fnc_int(cvar_t *cv, int value) {
*((int*)cv->data) = value;
}
void cvar_fnc_float(cvar_t *cv, int value) {
*((float*)cv->data) = cvar_itf(value);
}
void cvar_fnc_double(cvar_t *cv, int value) {
*((double*)cv->data) = (double)cvar_itf(value);
}
void cvar_fnc_color(cvar_t *cv, int value) {
*((uint*)cv->data) = (uint)value;
}
void cvar_fnc_fcolor(cvar_t *cv, int value) {
((float*)cv->data)[0] = ((float)((uint)((value >> 16) & 0xff))) * 255.0f;
((float*)cv->data)[1] = ((float)((uint)((value >> 8) & 0xff))) * 255.0f;
((float*)cv->data)[2] = ((float)((uint)(value & 0xff))) * 255.0f;
}
void cvar_fnc_scolor(cvar_t *cv, int value) {
*((uint*)cv->data) = ((uint)value) | 0xff000000;
}
void cvar_fnc_ccolor(cvar_t *cv, int value) {
*((uint*)cv->data) = ((uint)value) | ((*((uint*)cv->data)) & 0xff000000);
}
void cvar_fnc_acolor(cvar_t *cv, int value) {
*((uint*)cv->data) = ((uint)(float)(cvar_itf(value) * 255.0f)) | ((*((uint*)cv->data)) & 0x00ffffff);
}
void cvar_fnc_bind(cvar_t *cv, int value) {
((bind_t*)cv->data)->key = value;
}
cvar_t *cvar_add(const char *name, cvar_func *func, void *data, void *aux_data, int def, int min, int max, byte type, byte category, byte readonly, byte startup) {
cvar_t *cv = &sys.cvars[sys.n_cvars];
cv->func = func;
cv->data = data;
cv->aux_data = aux_data;
cv->value = cv->def = def;
cv->min = min;
cv->max = max;
cv->id = sys.n_cvars;
cv->readonly = readonly;
cv->startup = startup;
cv->type = type;
cv->category = category;
cv->name = name;
sys.n_cvars += 1;
return cv;
}
cvar_t *cvar_add_bool(const char *name, byte category, byte *data, byte def) {
cvar_t *cv = cvar_add(name, cvar_fnc_bool, data, NULL, (int)def, 0, 0, CVAR_BOOL, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_sbool(const char *name, byte category, cvar_func *func, byte *data, byte def, byte startup) {
cvar_t *cv = cvar_add(name, func, data, NULL, (int)def, 0, 0, CVAR_BOOL, category, 0, startup);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_wbool(const char *name, byte category, cvar_func *func, byte def) {
return cvar_add(name, func, NULL, NULL, (int)def, 0, 0, CVAR_BOOL, category, 0, 0);
}
cvar_t *cvar_add_int(const char *name, byte category, int *data, int def, int min, int max) {
cvar_t *cv = cvar_add(name, cvar_fnc_int, data, NULL, def, min, max, CVAR_INT, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_sint(const char *name, byte category, cvar_func *func, int *data, int def, int min, int max, byte startup) {
cvar_t *cv = cvar_add(name, func, data, NULL, def, min, max, CVAR_INT, category, 0, startup);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_byte(const char *name, byte category, byte *data, byte def, byte min, byte max) {
cvar_t *cv = cvar_add(name, cvar_fnc_bool, data, NULL, (int)def, (int)min, (int)max, CVAR_INT, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_rint(const char *name, byte category, int def, int min, int max) {
return cvar_add(name, cvar_fnc_void, NULL, NULL, def, min, max, CVAR_INT, category, 1, 0);
}
cvar_t *cvar_add_wint(const char *name, byte category, cvar_func *func, int def, int min, int max) {
return cvar_add(name, func, NULL, NULL, def, min, max, CVAR_INT, category, 0, 0);
}
cvar_t *cvar_add_float(const char *name, byte category, float *data, float def, float min, float max) {
cvar_t *cv = cvar_add(name, cvar_fnc_float, data, NULL, cvar_fti(def), cvar_fti(min), cvar_fti(max), CVAR_FLOAT, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_sfloat(const char *name, byte category, cvar_func *func, float *data, float def, float min, float max, byte startup) {
cvar_t *cv = cvar_add(name, func, data, NULL, cvar_fti(def), cvar_fti(min), cvar_fti(max), CVAR_FLOAT, category, 0, startup);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_double(const char *name, byte category, double *data, float def, float min, float max) {
cvar_t *cv = cvar_add(name, cvar_fnc_double, data, NULL, cvar_fti(def), cvar_fti(min), cvar_fti(max), CVAR_FLOAT, category, 0, 1);
if(data)
*data = (double)def;
return cv;
}
cvar_t *cvar_add_benum(const char *name, byte category, byte *data, const char **names, byte def, int states) {
cvar_t *cv = cvar_add(name, cvar_fnc_bool, data, names, (int)def, 0, states, CVAR_ENUM, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_sbenum(const char *name, byte category, cvar_func *func, byte *data, const char **names, byte def, int states, byte startup) {
cvar_t *cv = cvar_add(name, func, data, names, (int)def, 0, states, CVAR_ENUM, category, 0, startup);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_ienum(const char *name, byte category, int *data, const char **names, int def, int states) {
cvar_t *cv = cvar_add(name, cvar_fnc_int, data, names, def, 0, states, CVAR_ENUM, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_color(const char *name, byte category, uint *data, uint def) {
cvar_t *cv = cvar_add(name, cvar_fnc_scolor, data, NULL, (int)def, 0, 0, CVAR_COLOR, category, 0, 1);
if(data)
*data = def | 0xff000000;
return cv;
}
cvar_t *cvar_add_scolor(const char *name, byte category, cvar_func *func, uint *data, uint def, byte startup) {
cvar_t *cv = cvar_add(name, func, data, NULL, (int)def, 0, 0, CVAR_COLOR, category, 0, startup);
if(data)
*data = def | 0xff000000;
return cv;
}
cvar_t *cvar_add_acolor(const char *name, byte category, uint *data, uint def) {
cvar_t *cv = cvar_add(name, cvar_fnc_color, data, NULL, (int)def, 0, 0, CVAR_COLOR_ALPHA, category, 0, 1);
if(data)
*data = def;
return cv;
}
cvar_t *cvar_add_key(const char *name, byte bind, int def) {
cvar_t *cv = cvar_add(name, cvar_fnc_bind, &sys.binds[bind], NULL, def, 0, 0, CVAR_KEY, CVAR_BIND, 0, 1);
sys.binds[bind].key = def;
return cv;
}
void cvar_fmt_bool(char *str, int value) {
sprintf(str, value ? "true" : "false");
}
void cvar_fmt_int(char *str, int value) {
sprintf(str, "%d", value);
}
void cvar_fmt_float(char *str, int value) {
sprintf(str, "%.3f", cvar_itf(value));
}
void cvar_fmt_color(char *str, int value) {
sprintf(str, "%06x", (uint)value);
}
void cvar_fmt_acolor(char *str, int value) {
sprintf(str, "%08x", (uint)value);
}
void cvar_fmt_key(char *str, int value) {
if(value == 0) {
sprintf(str, "none");
}
else if(value >= -SCROLL_RIGHT && value <= -MOUSE_LEFT) {
sprintf(str, key_names[KEY_MOUSE_OFFSET - (value + MOUSE_LEFT)]);
}
else if(value >= KEYSYM_0 && value <= KEYSYM_9) {
sprintf(str, "%d", value - KEYSYM_0);
}
else if(value >= KEYSYM_A && value <= KEYSYM_Z) {
sprintf(str, "%c", 'a' + (char)(value - KEYSYM_A));
}
else if(value >= KEYSYM_F1 && value <= KEYSYM_F12) {
sprintf(str, "f%d", 1 + value - KEYSYM_F1);
}
else if(value >= KEYSYM_KP_0 && value <= KEYSYM_KP_9) {
sprintf(str, "kp%d", value - KEYSYM_KP_0);
}
else if(value >= KEYSYM_FIRST && value <= KEYSYM_LAST) {
sprintf(str, key_names[value - KEYSYM_FIRST]);
}
else {
sprintf(str, "#%d", value);
}
}
static const cvar_fmt_func cvar_fmt[] = {cvar_fmt_bool, cvar_fmt_int, cvar_fmt_float, NULL, cvar_fmt_color, cvar_fmt_acolor, cvar_fmt_key};
byte cvar_parse_bool(const char *str, int *value) {
if(str_eq_lower("1", str) || str_eq_lower("true", str) || str_eq_lower("on", str) || str_eq_lower("yes", str) || str_eq_lower("y", str)) {
*value = 1;
return 1;
}
else if(str_eq_lower("0", str) || str_eq_lower("false", str) || str_eq_lower("off", str) || str_eq_lower("no", str) || str_eq_lower("n", str)) {
*value = 0;
return 1;
}
return 0;
}
byte cvar_parse_int(const char *str, int *value) {
return str_parse_int(str, value, 0);
}
byte cvar_parse_float(const char *str, int *value) {
errno = 0;
float f = strtof(str, NULL);
if(errno)
return 0;
*value = cvar_fti(f);
return 1;
}
byte cvar_parse_color(const char *str, int *value) {
int c;
if((!str_parse_int(str, &c, -16)) || (c & 0xff000000))
return 0;
*value = c;
return 1;
}
byte cvar_parse_acolor(const char *str, int *value) {
return str_parse_int(str, value, -16);
}
byte cvar_parse_key(const char *str, int *value) {
int comp;
int max = 0;
int best = 0;
if(str[0] >= '0' && str[0] <= '9' && !(str[1])) {
*value = (str[0] - '0') + KEYSYM_0;
return 1;
}
else if(str[0] >= 'a' && str[0] <= 'z' && !(str[1])) {
*value = (str[0] - 'a') + KEYSYM_A;
return 1;
}
else if(str[0] >= 'A' && str[0] <= 'Z' && !(str[1])) {
*value = (str[0] - 'A') + KEYSYM_A;
return 1;
}
else if((str[0] == '#') && str[1] && str_parse_int(str+1, value, 10)) {
return 1;
}
else if((str_lower(str[0]) == 'f') && str[1] && str_parse_int(str+1, &comp, 10) && (comp >= 1) && (comp <= 25)) {
*value = (comp - 1) + KEYSYM_F1;
return 1;
}
else if((str_lower(str[0]) == 'k') && (str_lower(str[1]) == 'p') && (str[2] >= '0') && (str[2] <= '9') && !(str[3])) {
*value = (str[2] - '0') + KEYSYM_KP_0;
return 1;
}
else if(str_eq_lower("none", str)) {
*value = 0;
return 1;
}
for(int z = 0; z < KEY_MOUSE_OFFSET + SCROLL_RIGHT; z++) {
if((comp = str_cmp_lower(key_names[z], str)) > best) {
max = comp;
best = z;
}
}
if(max) {
*value = (best >= KEY_MOUSE_OFFSET) ? -(MOUSE_LEFT + best - KEY_MOUSE_OFFSET) : (KEYSYM_FIRST + best);
return 1;
}
return 0;
}
static const cvar_parse_func cvar_parse[] = {cvar_parse_bool, cvar_parse_int, cvar_parse_float, NULL, cvar_parse_color, cvar_parse_acolor, cvar_parse_key};
cvar_t *cvar_get(const char *key) {
return (cvar_t*)smap_get(&sys.cvar_map, key);
}
byte cvar_set(cvar_t *cv, const char *str, byte startup) {
if((cv->type == CVAR_ENUM) ? str_parse_enum(str, (const char**)cv->aux_data, cv->max, &cv->value) : cvar_parse[cv->type](str, &cv->value)) {
if(cv->type == CVAR_INT)
cv->value = CLAMP_VALUE(cv->value, cv->min, cv->max);
else if(cv->type == CVAR_FLOAT)
cv->value = cvar_fti(CLAMP_VALUE(cvar_itf(cv->value), cvar_itf(cv->min), cvar_itf(cv->max)));
if((!startup) || cv->startup)
cv->func(cv, cv->value);
sys.cfg_dirty |= startup ^ 1;
return 1;
}
else {
sys.cfg_dirty |= startup;
return 0;
}
}
void cvar_format(cvar_t *cv, char *str) {
if(cv->type == CVAR_ENUM) {
sprintf(str, "%s", ((const char**)cv->aux_data)[cv->value]);
}
else {
cvar_fmt[cv->type](str, cv->value);
}
}
byte cvar_byte(const char *name) {
return (byte)cvar_get(name)->value;
}
int cvar_int(const char *name) {
return cvar_get(name)->value;
}
float cvar_float(const char *name) {
return cvar_itf(cvar_get(name)->value);
}
uint cvar_color(const char *name) {
return (uint)cvar_get(name)->value;
}
int cvar_key(byte bind) {
return sys.cvars[bind].value;
}
int cvar_defkey(byte bind) {
return sys.cvars[bind].def;
}
void cvar_sdef(cvar_t *cv) {
cv->value = cv->def;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_setdef(const char *name) {
cvar_sdef(cvar_get(name));
}
void cvar_str(const char *name, char *str) {
cvar_format(cvar_get(name), str);
}
void cvar_sbool(cvar_t *cv, byte value) {
cv->value = (int)value;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_setbool(const char *name, byte value) {
cvar_sbool(cvar_get(name), value);
}
void cvar_toggle(const char *name) {
cvar_t *cv = cvar_get(name);
cv->value ^= 1;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_sint(cvar_t *cv, int value) {
cv->value = value;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_setint(const char *name, int value) {
cvar_sint(cvar_get(name), value);
}
void cvar_sfloat(cvar_t *cv, float value) {
cv->value = cvar_fti(value);
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_setfloat(const char *name, float value) {
cvar_sfloat(cvar_get(name), value);
}
void cvar_scolor(cvar_t *cv, uint value) {
cv->value = (int)value;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
void cvar_skey(byte bind, int value) {
cvar_t *cv = &sys.cvars[bind];
cv->value = (int)value;
cv->func(cv, cv->value);
sys.cfg_dirty = 1;
}
byte cvar_sstr(cvar_t *cv, const char *value) {
return cvar_set(cv, value, 0);
}
// void win_full(byte full);
// void cvar_fnc_full(cvar_t *cv, int value) {
// win_full(value);
// }
void win_sync(int sync);
void cvar_fnc_sync(cvar_t *cv, int value) {
win_sync(value);
}
void cvar_fnc_dlight(cvar_t *cv, int value) {
light_setup(value);
}
void tick_target(float tps);
void cvar_fnc_ticktarget(cvar_t *cv, int value) {
tick_target(cvar_itf(value));
}
void cvar_fnc_tex(cvar_t *cv, int value) {
cvar_fnc_bool(cv, value);
tex_config();
}
void cvar_fnc_ftex(cvar_t *cv, int value) {
cvar_fnc_float(cv, value);
tex_config();
}
void con_resize(int size);
void cvar_fnc_consize(cvar_t *cv, int value) {
con_resize(value);
}
void plr_debug(byte debug);
void plr_volume(byte channel, ushort volume);
void cvar_fnc_middebug(cvar_t *cv, int value) {
plr_debug((byte)value);
}
void cvar_fnc_volume(cvar_t *cv, int value) {
plr_volume((byte)(int)(cv->id - cvar_get(snd_cvar_volume[0])->id), (ushort)(cvar_itf(value) * 32767.0f));
}
void cvar_fnc_sound(cvar_t *cv, int value) {
}
void gfx_back_color(uint color);
void cvar_fnc_clight(cvar_t *cv, int value) {
gfx_back_color(0xff000000 | (uint)value);
}
void cvar_reg() {
#include "vars.h"
}
void theme_reg() {
style_t *style;
#define theme_add(str) \
style = (style_t*)tbl_push(&sys.themes);\
style->name = str;
#define theme_window(bdrtop, bdrbtm, top, btm, text) \
style->wbrdr_top = bdrtop;\
style->wbrdr_btm = bdrbtm;\
style->win_top = top;\
style->win_btm = btm;\
style->text_win = text;
#define theme_border(top, btm, size) \
style->brdr_top = top;\
style->brdr_btm = btm;\
style->border = size;
#define theme_background(top, btm) \
style->bg_top = top;\
style->bg_btm = btm;
#define theme_base(top, btm, text, label) \
style->fill_top = top;\
style->fill_btm = btm;\
style->text_base = text;\
style->text_label = label;
#define theme_field(top, btm, text) \
style->field_top = top;\
style->field_btm = btm;\
style->text_field = text;
#define theme_slider(handle) \
style->slider_width = handle;
#define theme_select(presstop, pressbtm, hovertop, hoverbtm, sel, cur) \
style->press_top = presstop;\
style->press_btm = pressbtm;\
style->hover_top = hovertop;\
style->hover_btm = hoverbtm;\
style->select = sel;\
style->cursor = cur;
#include "themes.h"
#undef theme_add
#undef theme_window
#undef theme_border
#undef theme_background
#undef theme_base
#undef theme_field
#undef theme_slider
#undef theme_select
sys.style_def = style;
}
byte cvar_load() {
char str[64];
char *lines;
char *line = NULL;
cvar_t *cv;
int pos;
if(!file_sread(&lines, sys.cfg_file)) {
return 0;
}
while(line = strtok(line ? NULL : lines, "\n")) {
for(pos = 0; line[pos]; pos++) {
if(line[pos] == '=')
break;
}
if(line[pos]) {
line[pos++] = 0;
if(!(cv = cvar_get(line))) {
loge(LOG_SYS, STR_CVAR_UNKNOWN, line);
continue;
}
if(sys.log_set != 0xff && cv->data == &sys.log_level) {
if(str_parse_enum(line+pos, (const char**)cv->aux_data, cv->max, &cv->value))
sys.log_set = (byte)cv->value;
else
loge(LOG_SYS, STR_CVAR_INVALID, cv->name, line+pos);
cv->value = (int)sys.log_level;
continue;
}
if(cvar_set(cv, line+pos, 1)) {
cvar_format(cv, str);
logt(LOG_SYS, "%s = %s", cv->name, str);
}
else {
loge(LOG_SYS, STR_CVAR_INVALID, cv->name, line+pos);
}
}
}
mem_free(lines);
return 1;
}
byte cvar_save() {
char str[64];
cvar_t *cv;
FILE *fd;
int err;
if(!(fd = fopen(sys.cfg_file, "wb"))) {
err = errno;
loge(LOG_IO, STR_CVAR_EWOPEN, sys.cfg_file, strerror(err), err);
return 0;
}
for(int z = 0; z < sys.n_cvars; z++) {
cv = &sys.cvars[z];
if(sys.log_set != 0xff && cv->data == &sys.log_level)
sprintf(str, "%s", ((const char**)cv->aux_data)[sys.log_set]);
else
cvar_format(cv, str);
fprintf(fd, "%s=%s\n", cv->name, str);
}
fclose(fd);
return 1;
}
void cvar_init() {
cvar_t *cv;
tbl_init(&sys.themes, 32, 1, sizeof(style_t), MEM_SYSTEM);
theme_reg();
cvar_reg();
smap_init(&sys.cvar_map, 1, MEM_SYSTEM);
for(int z = 0; z < sys.n_cvars; z++) {
cv = &sys.cvars[z];
smap_put(&sys.cvar_map, cv->name, cv);
}
cvar_load();
}
void cvar_end() {
cvar_save();
smap_clear(&sys.cvar_map);
tbl_clear(&sys.themes);
}
const char *cvar_getbind(byte bind) {
return STR_BIND_QUIT + (LOCALE_ELEM * bind);
}
const char *cvar_getkey(int key, char *buf) {
if(key == 0) {
return "---";
}
else if(key >= -SCROLL_RIGHT && key <= -MOUSE_LEFT) {
return STR_KEY_MOUSE_LEFT + (LOCALE_ELEM * -(key + MOUSE_LEFT));
}
else if(key >= KEYSYM_0 && key <= KEYSYM_9) {
sprintf(buf, "<%d>", key - KEYSYM_0);
return buf;
}
else if(key >= KEYSYM_A && key <= KEYSYM_Z) {
sprintf(buf, "<%c>", 'A' + (char)(key - KEYSYM_A));
return buf;
}
else if(key >= KEYSYM_F1 && key <= KEYSYM_F12) {
sprintf(buf, "F%d", 1 + key - KEYSYM_F1);
return buf;
}
else if(key >= KEYSYM_KP_0 && key <= KEYSYM_KP_9) {
sprintf(buf, "#%d", key - KEYSYM_KP_0);
return buf;
}
else if(key >= KEYSYM_FIRST && key <= KEYSYM_LAST) {
return STR_KEY_SPACE + (LOCALE_ELEM * (key - KEYSYM_FIRST));
}
else {
sprintf(buf, "[%d]", key);
return buf;
}
}