diff --git a/src/controller.c b/src/controller.c index 826919b..ce25682 100644 --- a/src/controller.c +++ b/src/controller.c @@ -2,6 +2,8 @@ #include "segment_renderer.h" #include +#define debug(x) printf("DEBUG: %s\n", (x)); + int *splits = 0; //pause for igt only @@ -36,27 +38,31 @@ void ctrl_record_segment(ctrl_binder *cb) { //need a condition for igt here //cb->delta_sl->segments[cb->current_segment].realtime = subts(segment->realtime, cb->rec_sl->segments[cb->current_segment].realtime); - struct timespec a, b; + struct timespec a, b, d; + char abuf[64]; + a = segment->realtime; b = cb->rec_sl->segments[cb->current_segment].realtime; - //b = (struct timespec) {10}; - char abuf[64]; - char bbuf[64]; - char dbuf[64]; - - struct timespec d = subts(a, b); - time_unparse(dbuf, FMT_SIZE, &d); + txtcol_set(cb->scrollers[2]->txtcol, time_unparse(abuf, FMT_SIZE, &a), cb->current_segment); if (time_cmp(b, a)) { //printf("GRN: %s - %s = %s\n", time_unparse(abuf, FMT_SIZE, &a), time_unparse(bbuf, FMT_SIZE, &b), dbuf); - cb->delta_sl->segments[cb->current_segment].realtime = subts(b, a); + d = cb->delta_sl->segments[cb->current_segment].realtime = subts(b, a); cb->delta_sl->segments[cb->current_segment].positive = 1; + txtcol_set(cb->scrollers[1]->txtcol, time_unparse(abuf, FMT_SIZE, &d), cb->current_segment); + text *txt = txtcol_get(cb->scrollers[1]->txtcol, cb->current_segment); + txt_color(txt, GREEN); } else { //printf("RED: %s - %s = %s\n", time_unparse(abuf, FMT_SIZE, &a), time_unparse(bbuf, FMT_SIZE, &b), dbuf); - cb->delta_sl->segments[cb->current_segment].realtime = subts(a, b); + d = cb->delta_sl->segments[cb->current_segment].realtime = subts(a, b); cb->delta_sl->segments[cb->current_segment].positive = 0; + txtcol_set(cb->scrollers[1]->txtcol, time_unparse(abuf, FMT_SIZE, &d), cb->current_segment); + text *txt = txtcol_get(cb->scrollers[1]->txtcol, cb->current_segment); + txt_color(txt, RED); } + //txtcol_set(cb->scrollers[1]->txtcol, time_unparse(abuf, FMT_SIZE, &d), cb->current_segment); + //cb->delta_sl->segments[cb->current_segment].realtime = subts((struct timespec){10}, segment->realtime); cb->delta_sl->segments[cb->current_segment].gametime = subts(segment->gametime, segment->gametime); } @@ -65,7 +71,6 @@ void ctrl_record_segment(ctrl_binder *cb) { void ctrl_start(ctrl_binder *cb) { //vars for easier code reading segment *current_segment = &cb->live_sl->segments[cb->current_segment]; - if (cb->timer.rta->running) { if (cb->rec_sl != NULL) { if (cb->current_segment < cb->live_sl->count) { @@ -73,28 +78,29 @@ void ctrl_start(ctrl_binder *cb) { } else { goto STOP; } - + + ctrl_scroller_op(cb, scroll_down); cb->current_segment++; - cb->sr->current = cb->current_segment; - scroll_down(cb->sr->scroller); + //cb->sr->current = cb->current_segment; + } else { STOP: cb->current_segment = 0; - cb->sr->running = false; - cb->sr->current = cb->current_segment; ghost_op(cb->timer, ghtimer_stop); - scroll_reset(cb->sr->scroller); + ctrl_scroller_op(cb, scroll_reset); + txtcol_op(cb->scrollers[1]->txtcol, txt_clear); //clear deltas } - + //pause timer if last split if (cb->current_segment == cb->live_sl->count) { - cb->sr->running = false; + ctrl_scroller_op(cb, scroll_down); + //cb->sr->running = false; ghost_op(cb->timer, ghtimer_pause); //for both igt and rta return; } } else { ghost_start(cb->timer); - cb->sr->running = true; + //cb->sr->running = true; } //cb->sr->current = cb->current_segment; @@ -103,13 +109,14 @@ STOP: void ctrl_bind_timer_renderer(ctrl_binder *cb, timer_renderer *timer) { cb->tr = timer; } -void ctrl_bind_segment_renderer(ctrl_binder *cb, segment_renderer *segmer) { + +/*void ctrl_bind_segment_renderer(ctrl_binder *cb, segment_renderer *segmer) { cb->sr = segmer; //yikes - cb->sr->scroller->delta_sl = *cb->delta_sl; - cb->sr->scroller->delta_segs = cb->delta_sl->segments; -} + //cb->sr->scroller->delta_sl = *cb->delta_sl; + //cb->sr->scroller->delta_segs = cb->delta_sl->segments; +}*/ ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl) { segment_list *zero = calloc(1, sizeof(segment_list)); @@ -122,6 +129,8 @@ ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl) { ctrl_binder *binder = calloc(1, sizeof(*binder)); binder->timer = timer; + binder->scroller_count = 0; + binder->scrollers = NULL; //binder->rec_sl = zero; binder->live_sl = zero; @@ -133,6 +142,20 @@ ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl) { return binder; } +void ctrl_add_scroller(ctrl_binder *cb, scroller *s) { + cb->scroller_count++; + //memory leak until i free it somewhere + cb->scrollers = realloc(cb->scrollers, sizeof(*cb->scrollers) * cb->scroller_count); + cb->scrollers[cb->scroller_count - 1] = s; + +} + +void ctrl_scroller_op(ctrl_binder *cb, void (*op)(scroller *s)) { + for (int i = 0; i < cb->scroller_count; i++) { + op(cb->scrollers[i]); + } +} + //bind recorded segments from file void ctrl_bind_segments(ctrl_binder *cb, segment_list *rec) { cb->rec_sl = rec; diff --git a/src/controller.h b/src/controller.h index 83df1c2..df9a089 100644 --- a/src/controller.h +++ b/src/controller.h @@ -10,14 +10,23 @@ //and to the input handler //and to the autosplitter +//change name to controller typedef struct ctrl_binder { ghost timer; segment_list *rec_sl, *live_sl, *delta_sl; timer_renderer *tr; - segment_renderer *sr; + //segment_renderer *sr; + scroller **scrollers; + int scroller_count; int current_segment; } ctrl_binder; +/*typedef struct controller { + ghost timer; + segment_list *rec_sl, *live_sl, *delta_sl; + timer_renderer *tr; +} controller;*/ + 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); @@ -25,4 +34,6 @@ void ctrl_bind_segments(ctrl_binder *cb, segment_list *sl); void ctrl_start(ctrl_binder *cb); void ctrl_pause(ghost timer); void ctrl_pause_igt(ghost timer); +void ctrl_add_scroller(ctrl_binder *cb, scroller *s); +void ctrl_scroller_op(ctrl_binder *cb, void (*op)(scroller *s)); //an operation for each scroller #endif diff --git a/src/main.c b/src/main.c index bd4382d..ba53a36 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,6 @@ #include #include "timer.h" #include "timer_renderer.h" -//#include "fmt.h" #include "segment_renderer.h" #include "controller.h" #include "splits.h" @@ -15,6 +14,8 @@ #define ERROR "Error: %s\n" +#define TXTCOL_LENGTH 64 + //global variables int windowWidth = 420; int windowHeight = 640; @@ -72,10 +73,39 @@ int main(int argc, char *argv[]) { (Vector2){(float)windowWidth, (float)windowHeight/8} ); - segment_renderer *sr = create_segment_renderer(segs, 0.0f, 0.0f); + //segment_renderer *sr = create_segment_renderer(segs, 0.0f, 0.0f); ctrl_bind_timer_renderer(binder, tr); - ctrl_bind_segment_renderer(binder, sr); + //ctrl_bind_segment_renderer(binder, sr); + + 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); + + char buffer[64]; + for (int i = 0; i < segs.count; i++) { + time_unparse(buffer, 64, &segs.segments[i].realtime); + txtcol_set(seg_names, segs.segments[i].name, i); + txtcol_set(seg_delta, " ", i); + txtcol_set(seg_times, buffer, i); + txt_pos(seg_names->column[i], (Vector2){0, i * font.baseSize/16}); + txt_pos(seg_delta->column[i], (Vector2){txtcol_widest(seg_names) + 10, i * font.baseSize/16}); + txt_pos(seg_times->column[i], (Vector2){0, i * font.baseSize/16}); + } + + //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); + + txtcol_op(seg_times, txt_left); float fontSize = (float)font.baseSize; @@ -84,12 +114,12 @@ int main(int argc, char *argv[]) { if (IsKeyPressed(KEY_P)) { ctrl_start(binder); + txtcol_op(seg_times, txt_left); } BeginDrawing(); ClearBackground(BLACK); - - render_segments(sr); + ctrl_scroller_op(binder, scroll_draw); //yummy render_timer(tr); EndDrawing(); } diff --git a/src/segment_renderer.c b/src/segment_renderer.c index ecda5be..ae874a4 100644 --- a/src/segment_renderer.c +++ b/src/segment_renderer.c @@ -1,17 +1,149 @@ #include "segment_renderer.h" +#include + +#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); -scroller *create_scroller(int c, segment_list sl) { +//txt funcs +text *txt_new(char *s, int length) { + text *t = calloc(1, sizeof(text)); + t->string = calloc(length, sizeof(char)); + t->length = length; + t->color = WHITE; + t->font = font; + txt_set(t, s); + return t; +} + +void txt_set(text *t, char *s) { + memcpy(t->string, s, t->length); +} + +void txt_free(text *t) { + free(t->string); + free(t); +} + +void txt_draw(text *t) { + DrawTextEx(t->font, t->string, t->pos, t->font.baseSize/SCALE, 1, t->color); +} + +void txt_print(text *t) { + //printf("%p\n", t->string); + printf("%s\n", t->string); +} + +void txt_color(text *t, Color color) { + t->color = color; +} + +void txt_pos(text *t, Vector2 pos) { + t->pos = pos; +} + +//left justify a column +void txt_left(text *t) { + Vector2 m = MeasureTextEx(t->font, t->string, t->font.baseSize/SCALE, 1); + t->pos = (Vector2) { + .x = windowWidth - m.x - 5, //minus 5 pixels so it looks nice + .y = t->pos.y, + }; +} + +void txt_clear(text *t) { + memset(t->string, 0, t->length); +} + +int txt_len(text *t) { + return strlen(t->string); +} + +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)); + tc->count = count; + tc->pos = (Vector2){0,0}; + tc->column = calloc(tc->count, sizeof(*tc->column)); + + for (int i = 0; i < count; i++) { + tc->column[i] = txt_new("new", length); + } + + return tc; +} + +text *txtcol_get(text_column *tc, int idx) { + return tc->column[idx]; +} + +void txtcol_set(text_column *tc, char *txt, int idx) { + txt_set(tc->column[idx], txt); +} + +void txtcol_free(text_column *tc) { + for (int i = 0; i < tc->count; i++) { + txt_free(tc->column[i]); + } + + free(tc->column); + free(tc); +} + +void txtcol_op(text_column *tc, void (*op)(text *)) { + for (int i = 0; i < tc->count; i++) { + op(tc->column[i]); + } +} + +int txtcol_longest(text_column *tc) { + int longest = 0; + int longidx, len; + for (int i = 0; i < tc->count; i++) { + len = txt_len(tc->column[i]); + if (longest < len) { + longest = len; + longidx = i; + } + } + return longidx; +} + +//returns the width of the widest string +int txtcol_widest(text_column *tc) { + int widest = 0; + for (int i = 0; i < tc->count; i++) { + int width = txt_width(tc->column[i]); + if (widest < width) { + widest = width; + } + } + + return widest; +} + +//put one column adjacent to another +void txtcol_adjacent(text_column *tc1, text_column *tc2, int offset) { + Vector2 m = MeasureTextEx(tc1->column[0]->font, tc1->column[txtcol_longest(tc1)]->string, tc1->column[0]->font.baseSize/SCALE, 1); + tc2->pos.x = tc1->pos.x + m.x + offset; +} + +//left justify a txtcol + +//scroller funcs +scroller *scroll_new(int c, text_column *tc) { scroller *s = calloc(1, sizeof(*s)); - s->sl = sl; + s->txtcol = tc; s->index = 0; s->view_index = 0; s->count = c; - s->segs = &sl.segments[s->view_index]; - return s; } @@ -21,26 +153,44 @@ void scroll_down(scroller *s) { return; } - if (s->view_index >= s->sl.count - s->count) { + if (s->view_index >= s->txtcol->count - s->count) { return; } s->view_index++; - s->segs = &s->sl.segments[s->view_index]; - s->delta_segs = &s->delta_sl.segments[s->view_index]; - //printf("%d %d\n", s->view_index, s->sl.count - s->count); + + for (int i = 0; i < s->txtcol->count; i++) { + text *txt = s->txtcol->column[i]; + txt_pos(txt, (Vector2){txt->pos.x, txt->pos.y - txt->font.baseSize/SCALE}); + } } void scroll_reset(scroller *s) { s->index = 0; s->view_index = 0; - s->segs = &s->sl.segments[s->view_index]; + + for (int i = 0; i < s->txtcol->count; i++) { + text *txt = s->txtcol->column[i]; + txt_pos(txt, (Vector2){txt->pos.x, i * txt->font.baseSize/SCALE}); + } + + //txtcol_op(s->txtcol, txt_clear); +} + + +//op(tc->column[i], (Vector2){tc->pos.x, tc->pos.y + i * font.baseSize/SCALE}); +void scroll_draw(scroller *s) { + for (int i = s->view_index; i < s->count + s->view_index; i++) { + txt_draw(txtcol_get(s->txtcol, i)); + //txt_print(txtcol_get(s->txtcol, i)); + } } 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; @@ -89,7 +239,7 @@ void render_segments(segment_renderer *sr) { 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) { + 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); @@ -98,6 +248,5 @@ void render_segments(segment_renderer *sr) { 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/segment_renderer.h index d8fe9c6..93d6050 100644 --- a/src/segment_renderer.h +++ b/src/segment_renderer.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "timer.h" #include "splits.h" @@ -13,22 +14,61 @@ extern Font font; //need to implement scrolling when total_splits > visible -typedef struct delta { +//a text string for rendering +typedef struct text { + char *string; + int length; + Color color; + Font font; + Vector2 pos; +} text; + +text *txt_new(char *s, int max); +void txt_set(text *t, char *s); +void txt_free(text *t); +void txt_draw(text *t); +void txt_print(text *t); +void txt_color(text *t, Color color); +void txt_pos(text *t, Vector2 pos); +void txt_left(text *t); +void txt_clear(text *t); + +//a list of text structs +typedef struct text_column { + text **column; + int count; + Vector2 pos; +} text_column; + +text_column *txtcol_new(int count, int length); +void txtcol_add(); +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); +int txtcol_longest(text_column *tc); +int txtcol_widest(text_column *tc); +void txtcol_op(text_column *tc, void (*op)(text *)); +void txtcol_adjacent(text_column *tc1, text_column *tc2, int offset); +//void txtcol_left(text_column *tc, int offset); + +typedef struct delta { //dont need this segment *seg; bool positive; } delta; +//scrolls through the text columns typedef struct scroller { - int count; + int count; //how many it should draw int index; //where the bar should be on the splits int view_index; //the first split displayed - segment *segs, *delta_segs; - segment_list sl, delta_sl; + text_column *txtcol; } scroller; -scroller *create_scroller(int c, segment_list sl); +scroller *scroll_new(int c, text_column *tc); void scroll_down(scroller *s); void scroll_reset(scroller *s); +void scroll_draw(scroller *s); typedef struct segment_renderer { float pos;