From f32b5e76ae997dc3c6766ef7742a2d0870fd962d Mon Sep 17 00:00:00 2001 From: sandyx Date: Fri, 24 Jan 2025 10:25:45 -0600 Subject: [PATCH] better splits.c --- src/controller.c | 3 +- src/controller.h | 4 +- src/fmt.c | 13 ++- src/fmt.h | 1 + src/main.c | 25 +++-- src/{splits.c => splits.c.no2} | 0 src/splits.h | 1 + src/splits2.c | 150 +++++++++++++++++++++++++++++ src/{segment_renderer.c => text.c} | 104 +++++++------------- src/{segment_renderer.h => text.h} | 45 ++------- 10 files changed, 228 insertions(+), 118 deletions(-) rename src/{splits.c => splits.c.no2} (100%) create mode 100644 src/splits2.c rename src/{segment_renderer.c => text.c} (63%) rename src/{segment_renderer.h => text.h} (65%) diff --git a/src/controller.c b/src/controller.c index 4711acd..b167bc0 100644 --- a/src/controller.c +++ b/src/controller.c @@ -2,7 +2,8 @@ #include #include "controller.h" -#include "segment_renderer.h" +//#include "segment_renderer.h" +//#include "text.h" #include "file.h" #define debug(x) printf("DEBUG: %s\n", (x)); diff --git a/src/controller.h b/src/controller.h index df9a089..81e487e 100644 --- a/src/controller.h +++ b/src/controller.h @@ -3,7 +3,7 @@ #include "timer.h" #include "splits.h" -#include "segment_renderer.h" +#include "text.h" #include "timer_renderer.h" #include //controller binds the timer to the splits @@ -29,7 +29,7 @@ typedef struct ctrl_binder { ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl); void ctrl_bind_timer_renderer(ctrl_binder *cb, timer_renderer *timer); -void ctrl_bind_segment_renderer(ctrl_binder *cb, segment_renderer *segmer); +//void ctrl_bind_segment_renderer(ctrl_binder *cb, segment_renderer *segmer); void ctrl_bind_segments(ctrl_binder *cb, segment_list *sl); void ctrl_start(ctrl_binder *cb); void ctrl_pause(ghost timer); diff --git a/src/fmt.c b/src/fmt.c index fa41ca2..f6f7186 100644 --- a/src/fmt.c +++ b/src/fmt.c @@ -26,6 +26,13 @@ struct timespec parse_time(char *str) { return time; } +//modifies original +void strip_leading_zero(char *s) { + if (s[0] == '0') { + memmove(s, s + 1, strlen(s)); + } +} + char *time_unparse(char *buffer, size_t len, struct timespec *ts) { struct tm *t = gmtime(&ts->tv_sec); if (t->tm_hour == 0 && t->tm_min != 0) { @@ -33,12 +40,14 @@ char *time_unparse(char *buffer, size_t len, struct timespec *ts) { } else if (t->tm_hour == 0 && t->tm_min == 0) { strftime(buffer, len, "%S.", gmtime(&ts->tv_sec)); } else { - strftime(buffer, len, "%T.", gmtime(&ts->tv_sec)); + strftime(buffer, len, "%H:%M:%S.", gmtime(&ts->tv_sec)); } - + double ns = timespec_to_double(*ts); ns = ns - (long)ns; snprintf(&buffer[strlen(buffer)], len, "%.2ld", (long)(ns*100)); + //strip_leading_zero(buffer); + return buffer; } diff --git a/src/fmt.h b/src/fmt.h index b5ce336..cdf5153 100644 --- a/src/fmt.h +++ b/src/fmt.h @@ -3,5 +3,6 @@ struct timespec parse_time(char *str); char *time_unparse(char *buffer, size_t len, struct timespec *ts); +void strip_leading_zero(char *s); #endif diff --git a/src/main.c b/src/main.c index 87f0ffb..43e5453 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,8 @@ #include #include "timer.h" #include "timer_renderer.h" -#include "segment_renderer.h" +//#include "segment_renderer.h" +#include "text.h" #include "controller.h" #include "splits.h" #include "file.h" @@ -92,6 +93,11 @@ int main(int argc, char *argv[]) { text_column *seg_names = txtcol_new(segs.count, TXTCOL_LENGTH); text_column *seg_delta = txtcol_new(segs.count, TXTCOL_LENGTH); text_column *seg_times = txtcol_new(segs.count, TXTCOL_LENGTH); + text_column *col[3] = {seg_names, seg_delta, seg_times}; + + for (int i = 0; i < 3; i++) { + txtcol_font(col[i], font); + } char buffer[64]; for (int i = 0; i < segs.count; i++) { @@ -107,15 +113,12 @@ int main(int argc, char *argv[]) { //lol //txtcol_adjacent(seg_names, seg_delta, 10); //txtcol_adjacent(seg_delta, seg_times, 10); - - scroller *scr1 = scroll_new(15, seg_names); - scroller *scr2 = scroll_new(15, seg_delta); - scroller *scr3 = scroll_new(15, seg_times); - ctrl_add_scroller(binder, scr1); - ctrl_add_scroller(binder, scr2); - ctrl_add_scroller(binder, scr3); + for (int i = 0; i < 3; i++) { + ctrl_add_scroller(binder, scroll_new(15, col[i])); + } + txtcol_op(seg_times, txt_strip); txtcol_op(seg_times, txt_left); float fontSize = (float)font.baseSize; @@ -126,9 +129,13 @@ int main(int argc, char *argv[]) { //need to make an input handler //so the loop doesnt get cluttered if (IsKeyPressed(KEY_P)) { + //txtcol_op(seg_times, txt_left); ctrl_start(binder); //ctrl_adjust_scrollers(binder); + txtcol_op(seg_times, txt_strip); + txtcol_op(seg_delta, txt_strip); txtcol_op(seg_times, txt_left); + //txtcol_op(seg_times, txt_strip); } if (IsKeyPressed(KEY_S)) { @@ -138,6 +145,8 @@ int main(int argc, char *argv[]) { BeginDrawing(); ClearBackground(BLACK); + if (ghost.rta->running) + DrawRectangle(0, (binder->scrollers[1]->index) * font.baseSize/16, windowWidth, (float)font.baseSize/16, BLUE); ctrl_scroller_op(binder, scroll_draw); //yummy render_timer(tr); EndDrawing(); diff --git a/src/splits.c b/src/splits.c.no2 similarity index 100% rename from src/splits.c rename to src/splits.c.no2 diff --git a/src/splits.h b/src/splits.h index f287361..12f919c 100644 --- a/src/splits.h +++ b/src/splits.h @@ -32,4 +32,5 @@ segment_list open_splits_file(const char *path); void render_splits(segment_list *segments); void debug_print_list(segment_list *segments); + #endif diff --git a/src/splits2.c b/src/splits2.c new file mode 100644 index 0000000..ff8dec6 --- /dev/null +++ b/src/splits2.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include "splits.h" +#include "fmt.h" +#include "xml.h" + +struct xml_node *get_node_by_name(struct xml_node *node, char *tag); +extern void error(const char *msg); //put this in a header + +typedef struct run_data { + char *game_name; + char *category_name; + char *offset; + int attempt_count; +} run_data; + +typedef struct xml_run_data { + struct xml_node *game_name; + struct xml_node *category_name; + struct xml_node *attempt_count; + struct xml_node *segments; +} xml_run_data; + +typedef struct xml_segment_data { + struct xml_node *name; + struct xml_node *rta; + struct xml_node *igt; + //can do more data later +} xml_segment_data; + +//ignore this for now +typedef struct r_segment { + char *name; + struct { + struct { + char *rta; + char *igt; + } split_time; + } split_times []; +} r_segment; +//utils + +static inline int get_file_size(FILE *file) { + int size; + fseek(file, 0L, SEEK_END); + size = ftell(file); + fseek(file, 0L, SEEK_SET); + return size; +} + +//create a segment from xml_segment_data +segment segment_from_data(xml_segment_data data) { + segment seg; + seg.name = xml_easy_content(data.name); + seg.realtime = parse_time( xml_easy_content(data.rta) ); + seg.gametime = parse_time( xml_easy_content(data.igt) ); + return seg; +} + +//create a segment from a node +segment segment_from_node(struct xml_node *node) { + xml_segment_data data; + struct xml_node *splittimes = get_node_by_name(node, "SplitTimes"); + struct xml_node *splittime = get_node_by_name(splittimes, "SplitTime"); + data.name = get_node_by_name(node, "Name"); + data.rta = get_node_by_name(splittime, "RealTime"); + data.igt = get_node_by_name(splittime, "GameTime"); + return segment_from_data(data); +} + +struct xml_node *get_node_by_name(struct xml_node *node, char *tag) { + for (int i = 0; i < xml_node_children(node); i++) { + struct xml_node *child = xml_node_child(node, i); + + char *name = xml_easy_name(child); + if ( strcmp(name, tag) == 0 ) { + free(name); + return child; + } + free(name); + } +} + +xml_run_data get_run_data(struct xml_document *doc) { + struct xml_node *root = xml_document_root(doc); + + //all the important stuff + xml_run_data data; + data.game_name = get_node_by_name(root, "GameName"); + data.category_name = get_node_by_name(root, "CategoryName"); + data.attempt_count = get_node_by_name(root, "AttemptCount"); + data.segments = get_node_by_name(root, "Segments"); + + return data; +} + +segment_list open_splits_file(const char *path) { + FILE *xml_file = fopen(path, "r"); + if (xml_file == NULL) { + error("Could not open file"); + } + + int xml_file_size = get_file_size(xml_file); + uint8_t buffer[xml_file_size]; //no more dirty calloc + + #pragma GCC diagnostic ignored "-Wunused-result" + fread(buffer, sizeof(uint8_t), xml_file_size, xml_file); + struct xml_document *xml = xml_parse_document(buffer, xml_file_size); + if (xml == NULL) { + error("Could not parse XML"); + } + + xml_run_data data = get_run_data(xml); + + int n = xml_node_children(data.segments); + segment *segs = calloc(n, sizeof(segment)); + for (int i = 0; i < n; i++) { + segs[i] = segment_from_node(xml_node_child(data.segments, i)); + } + + segment_list sl; + sl.segments = segs; + sl.count = n; + return sl; +} + +//only for the ruby script +char *save_fmt(segment_list *sl) { +#define buffer_size 8192 + static char buffer[buffer_size]; + char *bfp; + bfp = &buffer[0]; + memset(bfp, 0, buffer_size); + + char unparse_buffer[64]; + char *unp; + + for (int i = 0; i < sl->count; i++) { + unp = time_unparse(unparse_buffer, 64, &sl->segments[i].realtime); + sprintf(bfp, "%s=%s%%", sl->segments[i].name, unp); + bfp += strlen(bfp); + } + + printf("%s\n", buffer); + return buffer; +#undef buffer_size +} diff --git a/src/segment_renderer.c b/src/text.c similarity index 63% rename from src/segment_renderer.c rename to src/text.c index 087d163..0d3ccec 100644 --- a/src/segment_renderer.c +++ b/src/text.c @@ -1,12 +1,9 @@ -#include "segment_renderer.h" -#include +#include "text.h" +#include "fmt.h" -#define debug(x) printf("DEBUG: %s\n", (x)) #define SCALE 16 -extern int windowHeight; extern int windowWidth; -extern char *time_unparse(char *buffer, size_t len, struct timespec *ts); //txt funcs text *txt_new(char *s, int length) { @@ -14,7 +11,7 @@ text *txt_new(char *s, int length) { t->string = calloc(length, sizeof(char)); t->length = length; t->color = WHITE; - t->font = font; + //t->font = font; txt_set(t, s); return t; } @@ -30,6 +27,25 @@ void txt_free(text *t) { void txt_draw(text *t) { DrawTextEx(t->font, t->string, t->pos, t->font.baseSize/SCALE, 1, t->color); + //DrawRectangle(0, t->pos.y * 30, windowWidth, t->font.baseSize/16, BLUE); +} + +void txt_font(text *t, Font font) { + t->font = font; +} + +void txt_strip(text *t) { + strip_leading_zero(t->string); +} + +Rectangle txt_get_rect(text *t) { + Vector2 wh = MeasureTextEx(t->font, t->string, t->font.baseSize/SCALE, 1); + return (Rectangle) { + .x = t->pos.x, + .y = t->pos.y, + .width = wh.x, + .height = wh.y, + }; } void txt_print(text *t) { @@ -66,6 +82,8 @@ int txt_width(text *t) { Vector2 m = MeasureTextEx(t->font, t->string, t->font.baseSize/SCALE, 1); return m.x; } + + //text column funcs text_column *txtcol_new(int count, int length) { text_column *tc = calloc(1, sizeof(text_column)); @@ -103,6 +121,12 @@ void txtcol_op(text_column *tc, void (*op)(text *)) { } } +void txtcol_font(text_column *tc, Font font) { + for (int i = 0; i < tc->count; i++) { + tc->column[i]->font = font; + } +} + int txtcol_longest(text_column *tc) { int longest = 0; int longidx, len; @@ -150,8 +174,6 @@ void txtcol_save(text_column *tc) { fclose(file); } -//left justify a txtcol - //scroller funcs scroller *scroll_new(int c, text_column *tc) { scroller *s = calloc(1, sizeof(*s)); @@ -195,9 +217,14 @@ void scroll_reset(scroller *s) { //op(tc->column[i], (Vector2){tc->pos.x, tc->pos.y + i * font.baseSize/SCALE}); void scroll_draw(scroller *s) { + //Vector2 m = MeasureTextEx(tc1->column[0]->font, tc1->column[txtcol_longest(tc1)]->string, tc1->column[0]->font.baseSize/SCALE, 1); + //Vector2 m = MeasureTextEx(font, txtcol_get(s->txtcol, 1), ) + //DrawRectangle(0, (s->index) * 20, windowWidth, (float)font.baseSize/SCALE, BLUE); + for (int i = s->view_index; i < s->count + s->view_index; i++) { txt_draw(txtcol_get(s->txtcol, i)); } + } int scroll_widest_visible(scroller *s) { @@ -215,64 +242,3 @@ int scroll_widest_visible(scroller *s) { void destroy_scroller(scroller *s) { free(s); } -/* -//segment renderer funcs -segment_renderer *create_segment_renderer(segment_list sl, float y, float h) { - segment_renderer *sr = (segment_renderer *)calloc(1, sizeof(*sr)); - sr->pos = y; - sr->height = h; - sr->sl = sl; - sr->count = sl.count; - sr->current = 0; - sr->running = false; - sr->shader = NULL; - sr->scroller = create_scroller(15, sl); - return sr; -} - -void set_segment_renderer_shader(segment_renderer *sr, Shader *s) { - sr->shader = s; -} - -void set_segment_count(segment_renderer *sr, int c) { - sr->count = c; -} - -void destroy_segment_renderer(segment_renderer *sr) { - free(sr->scroller); - free(sr); -} - -Color color[2] = {RED, GREEN}; - -void render_segments(segment_renderer *sr) { - //need to not draw it if its the last split - //or if the timer isnt running - if (sr->running) { - DrawRectangle(0, (sr->scroller->index) * 30, windowWidth, (float)font.baseSize/16, BLUE); - } - - //draw a big rectangle the size of the segment thing - //DrawRectangle(0, 0, windowWidth, 90, BLACK); - - //for (int i = 0; i < sr->scroller->index; i++) { - //DrawTextEx(font, time_unparse(sr->strfmt, FMT_SIZE, &sr->scroller->delta_segs[i].realtime), (Vector2){280, 30 * i}, (float)font.baseSize/20, 2, GREEN); - //} - - for (int i = 0; i < sr->scroller->count; i++) { - //int j = i + sr->scroller->index; - //DrawText(sr->scroller->segs[i].name, (Vector2){10, 30 * i}.x, (Vector2){10, 30 * i}.y, 20, WHITE); - DrawTextEx(font, sr->scroller->segs[i].name, (Vector2){10, 30 * i}, (float)font.baseSize/16, 2, WHITE); - - //if the segment has been splitted upon, display the delta instead - if (sr->scroller->index < i) { - char *time = time_unparse(sr->strfmt, FMT_SIZE, &sr->scroller->segs[i].realtime); - Vector2 m = MeasureTextEx(font, time, font.baseSize/16, 2); - DrawTextEx(font, time, (Vector2){410 - m.x, 30 * i}, (float)font.baseSize/16, 2, WHITE); - } else { - char *time = time_unparse(sr->strfmt, FMT_SIZE, &sr->scroller->delta_segs[i].realtime); - Vector2 m = MeasureTextEx(font, time, font.baseSize/16, 2); - DrawTextEx(font, time_unparse(sr->strfmt, FMT_SIZE, &sr->scroller->delta_segs[i].realtime), (Vector2){410 - m.x, 30 * i}, (float)font.baseSize/16, 2, color[sr->scroller->delta_segs[i].positive]); - } - } -}*/ diff --git a/src/segment_renderer.h b/src/text.h similarity index 65% rename from src/segment_renderer.h rename to src/text.h index 92dd949..53790bd 100644 --- a/src/segment_renderer.h +++ b/src/text.h @@ -1,18 +1,10 @@ -#ifndef SEGMENT_RENDERER_H -#define SEGMENT_RENDERER_H +#ifndef TEXT_H +#define TEXT_H -#include -#include -#include +#include #include -#include "timer.h" -#include "splits.h" - -#define FMT_SIZE 64 - -extern Font font; - -//need to implement scrolling when total_splits > visible +#include +#include //a text string for rendering typedef struct text { @@ -29,9 +21,12 @@ void txt_free(text *t); void txt_draw(text *t); void txt_print(text *t); void txt_color(text *t, Color color); +void txt_font(text *t, Font font); +Rectangle txt_get_rect(text *t); void txt_pos(text *t, Vector2 pos); void txt_left(text *t); int txt_width(text *t); +void txt_strip(text *t); void txt_clear(text *t); //a list of text structs @@ -47,6 +42,7 @@ text *txtcol_get(text_column *tc, int idx); void txtcol_set(text_column *tc, char *txt, int idx); void txtcol_free(text_column *tc); void txtcol_draw(text_column *tc); +void txtcol_font(text_column *tc, Font font); int txtcol_longest(text_column *tc); int txtcol_widest(text_column *tc); void txtcol_op(text_column *tc, void (*op)(text *)); @@ -54,11 +50,6 @@ void txtcol_adjacent(text_column *tc1, text_column *tc2, int offset); //void txtcol_left(text_column *tc, int offset); void txtcol_save(text_column *tc); -typedef struct delta { //dont need this - segment *seg; - bool positive; -} delta; - //scrolls through the text columns typedef struct scroller { int count; //how many it should draw @@ -73,22 +64,4 @@ void scroll_reset(scroller *s); void scroll_draw(scroller *s); int scroll_widest_visible(scroller *s); -typedef struct segment_renderer { - float pos; - float height; - segment_list sl; - int count; - int current; - scroller *scroller; - bool running; - Shader *shader; - char strfmt[FMT_SIZE]; -} segment_renderer; - -segment_renderer *create_segment_renderer(segment_list sl, float y, float h); -void set_segment_renderer_shader(segment_renderer *sr, Shader *s); -void set_segment_count(segment_renderer *sr, int c); -void destroy_segment_renderer(segment_renderer *sr); -void render_segments(segment_renderer *sr); - #endif