better splits.c

main
sandyx 12 months ago
parent ca2c786c1e
commit f32b5e76ae

@ -2,7 +2,8 @@
#include <stdlib.h>
#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));

@ -3,7 +3,7 @@
#include "timer.h"
#include "splits.h"
#include "segment_renderer.h"
#include "text.h"
#include "timer_renderer.h"
#include <stdlib.h>
//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);

@ -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;
}

@ -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

@ -1,7 +1,8 @@
#include <raylib.h>
#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();

@ -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

@ -0,0 +1,150 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#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 <Segment> 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
}

@ -1,12 +1,9 @@
#include "segment_renderer.h"
#include <stdio.h>
#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]);
}
}
}*/

@ -1,18 +1,10 @@
#ifndef SEGMENT_RENDERER_H
#define SEGMENT_RENDERER_H
#ifndef TEXT_H
#define TEXT_H
#include <raylib.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "timer.h"
#include "splits.h"
#define FMT_SIZE 64
extern Font font;
//need to implement scrolling when total_splits > visible
#include <stdlib.h>
#include <raylib.h>
//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
Loading…
Cancel
Save