scrolling

main
sandyx 1 year ago
parent c35cda4f9b
commit 78cdbe6a05

2077
8uwa.lss

File diff suppressed because it is too large Load Diff

BIN
ghost

Binary file not shown.

@ -9,11 +9,10 @@ BUILD=build
C_FILES := $(shell find $(SRC) -name '*.c') C_FILES := $(shell find $(SRC) -name '*.c')
O_FILES += $(patsubst $(SRC)/%.c, $(BUILD)/%.o, $(C_FILES)) O_FILES += $(patsubst $(SRC)/%.c, $(BUILD)/%.o, $(C_FILES))
CFLAGS := -O0 -march=native -std=gnu99 CFLAGS := -O1 -march=native -std=gnu99
INCLUDE := INCLUDE :=
LIB := -lraylib LIB := -lraylib
ghost: $(APP_NAME) ghost: $(APP_NAME)
$(APP_NAME): $(O_FILES) $(APP_NAME): $(O_FILES)

@ -9,5 +9,5 @@ void main() {
//float mixval = distance(st, vec2(0, 1)); //float mixval = distance(st, vec2(0, 1));
//vec3 color = mix(color1, color2, mixval); //vec3 color = mix(color1, color2, mixval);
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); gl_FragColor = vec4(0.0, 1.0, 1.0, 0.4);
} }

@ -1,45 +1,62 @@
#include "controller.h" #include "controller.h"
#include "segment_renderer.h"
int *splits = 0; int *splits = 0;
void ctrl_pause(GHTimer *timer) { //pause for igt only
if (timer->paused) { inline void ctrl_pause_igt(ghost timer) {
ghtimer_resume(timer); if (timer.igt == NULL)
return;
if (timer.igt->paused) {
ghtimer_resume(timer.igt);
} else {
ghtimer_pause(timer.igt);
}
}
//pause for rta and igt
inline void ctrl_pause(ghost timer) {
if (timer.rta->paused) {
ghtimer_resume(timer.rta);
} else { } else {
ghtimer_pause(timer); ghtimer_pause(timer.rta);
} }
ctrl_pause_igt(timer);
} }
void ctrl_start(ctrl_binder *cb) { void ctrl_start(ctrl_binder *cb) {
if (cb->timer_rta->running) { if (cb->timer.rta->running) {
if (cb->rec_sl != NULL) { if (cb->rec_sl != NULL) {
if (cb->current_segment < cb->live_sl->cnt) { if (cb->current_segment < cb->live_sl->count) {
cb->live_sl->list[cb->current_segment]->realtime = ghtimer_time(cb->timer_rta); cb->live_sl->segments[cb->current_segment].realtime = ghtimer_time(cb->timer.rta);
//need to add a condition for igt //need to add a condition for igt
//cb->sr->scroller = scroll(cb->sr->scroller);
} else { } else {
goto STOP; goto STOP;
} }
cb->current_segment++; cb->current_segment++;
cb->sr->current = cb->current_segment; cb->sr->current = cb->current_segment;
scroll_down(cb->sr->scroller);
} else { } else {
STOP: STOP:
//increment run count
//ask user to save splits?
cb->current_segment = 0; cb->current_segment = 0;
cb->sr->running = false; cb->sr->running = false;
cb->sr->current = cb->current_segment; cb->sr->current = cb->current_segment;
ghtimer_stop(cb->timer_rta); //stop or reset, save splits ghtimer_stop(cb->timer.rta); //stop or reset, save splits
scroll_reset(cb->sr->scroller);
} }
//pause timer if last split //pause timer if last split
if (cb->current_segment == cb->live_sl->cnt) { if (cb->current_segment == cb->live_sl->count) {
cb->sr->running = false; cb->sr->running = false;
ghtimer_pause(cb->timer_rta); ghtimer_pause(cb->timer.rta);
return; return;
} }
} else { } else {
ghtimer_start(cb->timer_rta); ghost_start(cb->timer);
cb->sr->running = true; cb->sr->running = true;
} }
@ -53,9 +70,10 @@ void ctrl_bind_segment_renderer(ctrl_binder *cb, segment_renderer *segmer) {
cb->sr = segmer; cb->sr = segmer;
} }
ctrl_binder *create_ctrl_binder(GHTimer *rta, segment_list *sl) { ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl) {
ctrl_binder *binder = calloc(1, sizeof(ctrl_binder)); ctrl_binder *binder = calloc(1, sizeof(ctrl_binder));
binder->timer_rta = rta; binder->timer = timer;
binder->rec_sl = sl; binder->rec_sl = sl;
binder->live_sl = sl; binder->live_sl = sl;
return binder; return binder;

@ -11,16 +11,17 @@
//and to the autosplitter //and to the autosplitter
typedef struct ctrl_binder { typedef struct ctrl_binder {
GHTimer *timer_rta, *timer_igt; ghost timer;
segment_list *rec_sl, *live_sl; segment_list *rec_sl, *live_sl;
timer_renderer *tr; timer_renderer *tr;
segment_renderer *sr; segment_renderer *sr;
int current_segment; int current_segment;
} ctrl_binder; } ctrl_binder;
ctrl_binder *create_ctrl_binder(GHTimer *rta, segment_list *sl); ctrl_binder *create_ctrl_binder(ghost timer, segment_list *sl);
void ctrl_bind_timer_renderer(ctrl_binder *cb, timer_renderer *timer); 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_start(ctrl_binder *cb); void ctrl_start(ctrl_binder *cb);
void ctrl_pause(GHTimer *timer); void ctrl_pause(ghost timer);
void ctrl_pause_igt(ghost timer);
#endif #endif

@ -0,0 +1,6 @@
#ifndef FILE_H
#define FILE_H
#endif

@ -0,0 +1,44 @@
#include <time.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "fmt.h"
//maybe should just move the whole function here
extern double timespec_to_double(struct timespec ts);
struct timespec parse_time(char *str) {
struct timespec time;
time_t hour_t;
time_t min_t;
time_t sec_t;
time_t nsec_t;
sscanf(str, "%ld:%ld:%ld.%ld", &hour_t, &min_t, &sec_t, &nsec_t);
time.tv_sec = (hour_t * 3600) + (min_t * 60) + (sec_t);
time.tv_nsec = nsec_t * 1e+7f;
//printf("%lf\n", timespec_to_double(time));
//180.500_000_000
return time;
}
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) {
strftime(buffer, len, "%M:%S.", gmtime(&ts->tv_sec));
} 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));
}
double ns = timespec_to_double(*ts);
ns = ns - (long)ns;
snprintf(&buffer[strlen(buffer)], len, "%.2ld", (long)(ns*100));
return buffer;
}

@ -0,0 +1,7 @@
#ifndef FMT_H
#define FMT_H
struct timespec parse_time(char *str);
char *time_unparse(char *buffer, size_t len, struct timespec *ts);
#endif

@ -1,11 +0,0 @@
//gsl_reader.c
#include "parser.h"
void init_autosplit(const char *path) {
char *file_buffer = load_file(path);
char *line;
for (line = get_next_line(file_buffer, 0); line != NULL; line = get_next_line(file_buffer, 0)) {
printf("%s\n", line);
}
}

@ -1 +0,0 @@
#ifndef GSL_READER

@ -1,21 +0,0 @@
#ifndef LAYOUT_MGR_H
#define LAYOUT_MGR_H
#include <raylib.h>
#include <stdlib.h>
#include <stdbool.h>
extern int windowWidth;
extern int windowHeight;
typedef struct layout_background {
Texture2D texture;
Shader shader;
} layout_background;
layout_background *layout_background_new(Color color) {
Image blank = GenImageColor(windowWidth, windowHeight, BLANK);
Texture2D texture = LoadTextureFromImage(blank);
UnloadImage(blank);
}
#endif

@ -1,5 +0,0 @@
#include <dlfcn.h>
void load_module(const char *path) {
}

@ -1,10 +1,12 @@
#include <raylib.h> #include <raylib.h>
#include "timer.h" #include "timer.h"
#include "timer_renderer.h" #include "timer_renderer.h"
//#include "fmt.h"
#include "segment_renderer.h" #include "segment_renderer.h"
#include "controller.h" #include "controller.h"
//#include "scanner.h" //#include "scanner.h"
#include "splits.h" #include "splits.h"
//#include "parser.c"
#include <stdio.h> #include <stdio.h>
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
@ -13,6 +15,8 @@
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif
#define ERROR "Error: %s\n"
//global variables //global variables
int windowWidth = 420; int windowWidth = 420;
int windowHeight = 640; int windowHeight = 640;
@ -21,6 +25,13 @@ int remote_state = 0;
Font font; Font font;
//extern this for other files
void error(const char *msg) {
fprintf(stderr, ERROR, msg);
exit(EXIT_FAILURE);
}
//extern void print_xml(const char *path);
//testing control function //testing control function
void control(void) { void control(void) {
static int last_state; static int last_state;
@ -32,43 +43,51 @@ void control(void) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
//font = LoadFontEx("/usr/share/fonts/CozetteVector.ttf", 400, 0, 0);
// GenTextureMipmaps(&font.texture);
if (argc < 2) {
error("gimme file");
exit(EXIT_FAILURE);
}
segment_list segs = open_splits_file(argv[1]);
//size of window can be determined by height of all components visible //size of window can be determined by height of all components visible
InitWindow(windowWidth, windowHeight, "Ghost"); InitWindow(windowWidth, windowHeight, "Ghost");
SetTargetFPS(60); SetTargetFPS(60);
//use libxml or something Image blank = GenImageColor(640, 420, BLANK);
segment_list segments = open_splits_file("test/splits.ghs"); Texture2D texture = LoadTextureFromImage(blank);
GHTimer *timer = ghtimer_new();
//make a layout manager for these
timer_renderer *tr = create_timer_renderer(timer, (Vector2){0.0f, 90.0f}, (Vector2){(float)windowWidth, (float)windowHeight/8});
segment_renderer *sr = create_segment_renderer(&segments, 0.0f, 0.0f);
//layout manager
Image blank = GenImageColor(windowWidth, windowHeight, BLANK);
Texture2D texture = LoadTextureFromImage(blank);
Shader shader = LoadShader(0, "shaders/frag.glsl"); Shader shader = LoadShader(0, "shaders/frag.glsl");
UnloadImage(blank); UnloadImage(blank);
set_segment_renderer_shader(sr, &shader); font = LoadFontEx("/usr/share/fonts/CozetteVector.ttf", 400, 0, 0);
set_timer_shader(tr, &shader);
ctrl_binder *cb = create_ctrl_binder(timer, &segments);
ctrl_bind_timer_renderer(cb, tr);
ctrl_bind_segment_renderer(cb, sr);
font = LoadFontEx("/usr/share/fonts/CozetteVector.ttf", 400, 0, 0);
GenTextureMipmaps(&font.texture); GenTextureMipmaps(&font.texture);
ghost ghost = ghost_new();
ctrl_binder *binder = create_ctrl_binder(ghost, &segs);
//make a layout manager for these
timer_renderer *tr = create_timer_renderer(ghost, (Vector2){0.0f, windowHeight/8 * 6}, (Vector2){(float)windowWidth, (float)windowHeight/8});
segment_renderer *sr = create_segment_renderer(segs, 0.0f, 0.0f);
float fontSize = (float)font.baseSize; ctrl_bind_timer_renderer(binder, tr);
ctrl_bind_segment_renderer(binder, sr);
//uint8_t buffer[1024];
// float fontSize = (float)font.baseSize;
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
ghtimer_tick(timer); ghost_tick(ghost);
//ghtimer_timestring(ghost.rta, buffer);
if (IsKeyPressed(KEY_P)) { if (IsKeyPressed(KEY_P)) {
ctrl_start(cb); ctrl_start(binder);
} }
BeginDrawing(); BeginDrawing();
//BeginShaderMode(shader); //BeginShaderMode(shader);
ClearBackground(BLACK); ClearBackground(BLACK);
@ -78,10 +97,11 @@ int main(int argc, char *argv[]) {
//need to make this not weird //need to make this not weird
render_segments(sr); render_segments(sr);
render_timer(tr); render_timer(tr);
EndShaderMode(); //EndShaderMode();
//printf("cunt\n");
EndDrawing(); EndDrawing();
} }
ghtimer_delete(timer); //ghost_delete(ghost);
CloseWindow(); CloseWindow();
} }

@ -1,155 +0,0 @@
#include "parser.h"
/*
I've separated this out into its own file
so it can be used anywhere, and be compiled
with any C standard that supports strtok_r.
*/
size_t get_file_len(FILE *file) {
fseek(file, 0, SEEK_END);
unsigned int len = ftell(file);
fseek(file, 0, SEEK_SET);
return len;
}
/*
loads a files and mallocates a buffer
and returns a pointer to it.
remember to free the buffer when you're done.
*/
char *load_file(const char *path) {
FILE *file = fopen(path, "r");
if (file == NULL) {
printf("%s\n", "Could not open file.");
return NULL;
}
size_t len = get_file_len(file);
char *buffer = malloc(len);
#pragma GCC diagnostic ignored "-Wunused-result"
fread(buffer, len, 1, file);
fclose(file);
return buffer;
}
char *get_next_line(char* buffer, bool clear) {
static char *saveptr;
static char *line;
if (clear) {
saveptr = NULL;
line = NULL;
return NULL;
}
if (saveptr == NULL) {
line = strtok_r(buffer, "\n", &saveptr);
} else {
if (line == NULL) {
saveptr = NULL;
return NULL;
}
line = strtok_r(NULL, "\n", &saveptr);
}
return line;
}
char *get_next_token(char *buffer, char *delim, bool clear) {
static char *saveptr;
static char *token;
if (clear) {
saveptr = NULL;
token = NULL;
return NULL;
}
if (saveptr == NULL) {
token = strtok_r(buffer, delim, &saveptr);
} else {
if (token == NULL) {
saveptr = NULL;
return NULL;
}
token = strtok_r(NULL, delim, &saveptr);
}
return token;
}
//find first non space char;
//copy that index to beginning of string
//replace last space with null
char *strip(char *str, char c) {
char *idx;
int len = strlen(str);
//find index of first non space char
for (int i = 0; i < len; i++) {
if (str[i] != c) {
idx = &str[i];
break;
}
}
//voodoo math
memcpy(str, idx, len+1 - (idx - str));
return str;
}
//cut off the front
char *cut_front(char *str, char c) {
char *idx;
int len = strlen(str);
//find index of first matching char
for (int i = 0; i < len; i++) {
if (str[i] == c) {
idx = &str[i];
break;
}
}
return idx + 1;
}
//cut off the back
char *cut_back(char *str, char c) {
char *idx;
char *cpy = strdup(str);
int len = strlen(str);
//find index of first matching char
for (int i = 0; i < len; i++) {
if (cpy[i] == c) {
cpy[i] = 0;
break;
}
}
return cpy;
}
//strip a string in place
char *strip_all(char *str) {
char *write = str;
char *read = str;
do {
if (*read != ' ') {
*write++ = *read;
}
} while (*read++ && *read != ' ');
return str;
}

@ -1,18 +0,0 @@
#ifndef PARSER_H
#define PARSER_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
size_t get_file_len(FILE *file);
char *load_file(const char *path);
char *get_next_line(char* buffer, bool clear);
char *get_next_token(char *buffer, char *delim, bool clear);
char *strip_all(char *str);
char *strip(char *str, char c);
char *cut_front(char *str, char c);
char *cut_back(char *str, char c);
#endif

@ -4,15 +4,48 @@ extern int windowHeight;
extern int windowWidth; extern int windowWidth;
extern char *time_unparse(char *buffer, size_t len, struct timespec *ts); extern char *time_unparse(char *buffer, size_t len, struct timespec *ts);
segment_renderer *create_segment_renderer(segment_list *sl, float y, float h) { scroller *create_scroller(int c, segment_list sl) {
segment_renderer *sr = calloc(1, sizeof(segment_renderer)); scroller *s = calloc(1, sizeof(*s));
s->sl = sl;
s->index = 0;
s->view_index = 0;
s->count = c;
s->segs = &sl.segments[s->view_index];
return s;
}
void scroll_down(scroller *s) {
if (s->index < s->count - 1) {
s->index++;
return;
}
if (s->view_index >= s->sl.count - s->count) {
return;
}
s->view_index++;
s->segs = &s->sl.segments[s->view_index];
//printf("%d %d\n", s->view_index, s->sl.count - s->count);
}
void scroll_reset(scroller *s) {
s->index = 0;
s->view_index = 0;
s->segs = &s->sl.segments[s->view_index];
}
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->pos = y;
sr->height = h; sr->height = h;
sr->seglist = sl; sr->sl = sl;
sr->count = sl->cnt; sr->count = sl.count;
sr->current = 0; sr->current = 0;
sr->running = false; sr->running = false;
sr->shader = NULL; sr->shader = NULL;
sr->scroller = create_scroller(13, sl);
//printf("cunt %p\n%p\n", s, sr->scroller);
return sr; return sr;
} }
@ -29,25 +62,20 @@ void destroy_segment_renderer(segment_renderer *sr) {
} }
void render_segments(segment_renderer *sr) { void render_segments(segment_renderer *sr) {
if (sr->shader != NULL) {
BeginShaderMode(*sr->shader);
}
//need to not draw it if its the last split //need to not draw it if its the last split
//or if the timer isnt running //or if the timer isnt running
if (sr->running) { if (sr->running) {
DrawRectangle(0, (sr->current) * 30, windowWidth, (float)font.baseSize/16, BLUE); DrawRectangle(0, (sr->scroller->index) * 30, windowWidth, (float)font.baseSize/16, BLUE);
} }
//draw a big rectangle the size of the segment thing //draw a big rectangle the size of the segment thing
DrawRectangle(0, 0, windowWidth, 90, WHITE); //DrawRectangle(0, 0, windowWidth, 90, BLACK);
if (sr->shader != NULL) {
EndShaderMode();
}
for (int i = 0; i < sr->count; i++) { for (int i = 0; i < sr->scroller->count; i++) {
DrawTextEx(font, sr->seglist->list[i]->name, (Vector2){10, 30 * i}, (float)font.baseSize/16, 2, BLACK); //DrawText(sr->scroller->segs[i].name, (Vector2){10, 30 * i}.x, (Vector2){10, 30 * i}.y, 20, WHITE);
DrawTextEx(font, time_unparse(sr->strfmt, FMT_SIZE, &sr->seglist->list[i]->realtime), (Vector2){200, 30 * i}, (float)font.baseSize/16, 2, BLACK); DrawTextEx(font, sr->scroller->segs[i].name, (Vector2){10, 30 * i}, 20, 2, WHITE);
DrawTextEx(font, time_unparse(sr->strfmt, FMT_SIZE, &sr->scroller->segs[i].realtime), (Vector2){350, 30 * i}, (float)font.baseSize/16, 2, WHITE);
} }
} }

@ -13,18 +13,31 @@ extern Font font;
//need to implement scrolling when total_splits > visible //need to implement scrolling when total_splits > visible
typedef struct scroller {
int count;
int index; //where the bar should be on the splits
int view_index; //the first split displayed
segment *segs;
segment_list sl;
} scroller;
scroller *create_scroller(int c, segment_list sl);
void scroll_down(scroller *s);
void scroll_reset(scroller *s);
typedef struct segment_renderer { typedef struct segment_renderer {
float pos; float pos;
float height; float height;
segment_list *seglist; segment_list sl;
int count; int count;
int current; int current;
scroller *scroller;
bool running; bool running;
Shader *shader; Shader *shader;
char strfmt[FMT_SIZE]; char strfmt[FMT_SIZE];
} segment_renderer; } segment_renderer;
segment_renderer *create_segment_renderer(segment_list *sl, float y, float h); 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_renderer_shader(segment_renderer *sr, Shader *s);
void set_segment_count(segment_renderer *sr, int c); void set_segment_count(segment_renderer *sr, int c);
void destroy_segment_renderer(segment_renderer *sr); void destroy_segment_renderer(segment_renderer *sr);

@ -1,143 +1,233 @@
#include <raylib.h>
#include <stdlib.h>
#include <math.h>
#include "splits.h" #include "splits.h"
#include "parser.h"
#include "timer.h" #include "timer.h"
#include <math.h> #include "xml.h"
#include "fmt.h"
#include <raylib.h>
extern Font font; extern Font font;
extern void error(const char *msg);
void print_segment(segment *seg) { void print_segment(segment *seg) {
printf("%s\n", seg->name); printf("%s\n", seg->name);
//printf("%ld.%ld\n", seg->realtime.tv_sec, seg->realtime.tv_nsec); //printf("%ld.%ld\n", seg->realtime.tv_sec, seg->realtime.tv_nsec);
} }
struct timespec parse_time(char *str) { //utils
struct timespec time; int get_file_size(FILE *file) {
int size;
fseek(file, 0L, SEEK_END);
size = ftell(file);
fseek(file, 0L, SEEK_SET);
return size;
}
time_t hour_t; void log_node(struct xml_node *node) {
time_t min_t; //struct xml_node *root = xml_document_root(document);
time_t sec_t; struct xml_string *name = xml_node_name(node);
time_t nsec_t; struct xml_string *content = xml_node_content(node);
int name_len = xml_string_length(name);
int content_len = xml_string_length(content);
uint8_t *name_buffer = calloc(name_len + 1, sizeof(uint8_t));
uint8_t *content_buffer = calloc(content_len + 1, sizeof(uint8_t));
xml_string_copy(name, name_buffer, name_len);
xml_string_copy(content, content_buffer, content_len);
printf("%s: %s\n", name_buffer, content_buffer);
free(name_buffer);
free(content_buffer);
}
sscanf(str, "%ld:%ld:%ld.%ld", &hour_t, &min_t, &sec_t, &nsec_t); //print children of node
void enum_node(struct xml_node *node) {
int children;
children = xml_node_children(node);
time.tv_sec = (hour_t * 3600) + (min_t * 60) + (sec_t); for (int i = 0; i < children; i++) {
time.tv_nsec = nsec_t * 1e+7f; struct xml_node *child = xml_node_child(node, i);
log_node(child);
//enum_node(child);
}
}
//printf("%lf\n", timespec_to_double(time)); void enum_node_recursive(struct xml_node *node) {
//180.500_000_000 int children;
children = xml_node_children(node);
return time; for (int i = 0; i < children; i++) {
struct xml_node *child = xml_node_child(node, i);
log_node(child);
enum_node(child);
}
} }
char *time_unparse(char *buffer, size_t len, struct timespec *ts) { bool xml_name_compare(struct xml_node *node, const char *str) {
struct tm *t = gmtime(&ts->tv_sec); bool equal;
if (t->tm_hour == 0 && t->tm_min != 0) { struct xml_string *name = xml_node_name(node);
strftime(buffer, len, "%M:%S.", gmtime(&ts->tv_sec)); int len = xml_string_length(name);
} else if (t->tm_hour == 0 && t->tm_min == 0) {
strftime(buffer, len, "%S.", gmtime(&ts->tv_sec)); uint8_t *buffer = calloc(len + 1, sizeof(uint8_t));
} else { xml_string_copy(name, buffer, len);
strftime(buffer, len, "%T.", gmtime(&ts->tv_sec)); equal = !strcmp(buffer, str);
} free(buffer);
return equal;
double ns = timespec_to_double(*ts);
ns = ns - (long)ns;
snprintf(&buffer[strlen(buffer)], len, "%.2ld", (long)(ns*100));
return buffer;
} }
segment *read_segment(char *file, char *line) { typedef struct segment_nodes {
segment *seg = calloc(1, sizeof(segment)); struct xml_node **nodes;
int count;
while (strcmp(line, "end")) { } segment_nodes;
char *key = strip(cut_back(line, ':'), ' ');
char *value = cut_front(strip(line, ' '), ' '); segment_nodes get_node_children(struct xml_node *node) {
segment_nodes segments;
segments.count = xml_node_children(node);
printf("get_node_children: %d\n", segments.count);
segments.nodes = calloc(segments.count, sizeof(struct xml_node *));
for (int i = 0; i < segments.count; i++) {
segments.nodes[i] = xml_node_child(node, i);
}
return segments;
}
if (!strcmp(key, "name")) { uint8_t *convert(struct xml_string *xml) {
seg->name = strdup(value); int len = xml_string_length(xml);
} uint8_t *buffer = calloc(len + 1, sizeof(uint8_t));
xml_string_copy(xml, buffer, len);
return buffer;
}
if (!strcmp(key, "gametime")) { struct xml_string *get_name_string(struct xml_node *node) {
seg->gametime = parse_time(value); for (int i = 0; i < xml_node_children(node); i++) {
} struct xml_node *child = xml_node_child(node, i);
if (xml_name_compare(child, "Name")) {
return xml_node_content(child);
}
}
if (!strcmp(key, "realtime")) { return NULL;
seg->realtime = parse_time(value); }
}
if (!strcmp(key, "best")) { uint8_t **extract(segment_nodes segments, struct xml_string *(operation)(struct xml_node *)) {
seg->best = parse_time(value); struct xml_string **xml_strings = calloc(segments.count, sizeof(struct xml_string *));
}
for (int i = 0; i < segments.count; i++) {
xml_strings[i] = operation(segments.nodes[i]);
}
free(key); uint8_t **strings = calloc(segments.count, sizeof(uint8_t *));
line = get_next_line(file, 0);
} for (int i = 0; i < segments.count; i++) {
strings[i] = convert(xml_strings[i]);
}
return seg; return strings;
} }
segment_list open_splits_file(const char *path) { struct xml_node *get_segments_node(struct xml_node *root) {
char *file = load_file(path); struct xml_node *child;
int idx = 0;
int cnt = 0; for (int i = 0; i < xml_node_children(root); i++) {
segment_list segments = {0}; struct xml_node *child = xml_node_child(root, i);
if (xml_name_compare(child, "Segments")) {
char *line = get_next_line(file, 0); return child;
}
//enumerate segments }
while (line != NULL) {
if (!strcmp(line, "segment")) { return NULL;
segments.cnt++; }
}
line = get_next_line(file, 0);
}
//reset strtok_r and create fresh file since it modified it
get_next_line(NULL, 1);
free(file); file = load_file(path);
//make an extra one so the last segment->next == NULL;
segments.list = calloc(cnt + 1, sizeof(segment *));
line = get_next_line(file, 0);
//create segments
while (line != NULL) {
if (!strcmp(line, "segment")) {
segments.list[idx] = read_segment(file, line);
idx++;
}
line = get_next_line(file, 0);
}
for (int i = 0; i < cnt; i++) { struct xml_string **get_segment_names(struct xml_node *segments) {
segments.list[i]->next = segments.list[i+1]; int segments_count;
} struct xml_string **segment_names;
//check segments_count = xml_node_children(segments);
/*for (int i = 0; i < idx; i++) {
printf("%p\n", segments[i]); }
}*/
void print_all_segment_names(struct xml_node *node) {
//no leaky struct xml_node *segments = get_segments_node(node);
free(file); if (!segments) {
error("couldnt get em");
}
return segments; enum_node(segments);
} }
/* segment *create_segment(char *name) {
void render_splits(segment_list *segments) { segment *seg = calloc(1, sizeof(segment));
seg->name = name;
return seg;
}
segment_list open_splits_file(const char *path) {
FILE *xml_file = fopen(path, "r");
if (!xml_file) {
error("Could not open file");
}
int xml_file_size = get_file_size(xml_file);
uint8_t *buffer = calloc(sizeof(uint8_t), xml_file_size);
int no = fread(buffer, sizeof(uint8_t), xml_file_size, xml_file);
struct xml_document *xml = xml_parse_document(buffer, xml_file_size);
if (!xml) {
error("Could not parse xml");
}
printf("splits.c: parsed %s successfully\n", path);
int children = 0;
struct xml_node *root = xml_document_root(xml);
struct xml_node *segments_node = get_segments_node(root);
segment_nodes segments = get_node_children(segments_node);
uint8_t **segment_names = extract(segments, get_name_string);
printf("open_splits_file: %d\n", segments.count);
for (int i = 0; i < segments.count; i++) {
printf("%s\n", segment_names[i]);
}
segment_list seglist = {0};
printf("open_splits_file: %d\n", segments.count);
printf("%ld\n", segments.count * sizeof(segment));
long long what = segments.count * sizeof(segment);
printf("what: %lld\n", what);
segment *segs = malloc(1008);
printf("?\n");
for (int i = 0; i < segments.count; i++) {
segs[i].name = segment_names[i];
//segs[i].realtime = (struct timespec){0};
}
seglist.segments = segs;
seglist.count = segments.count;
return seglist;
}
/*void render_splits(segment_list *segments) {
char buffer[100]; char buffer[100];
for (int i = 0; i < segments->cnt; i++) { for (int i = 0; i < segments->count; i++) {
DrawTextEx(font, segments->list[i]->name, (Vector2){10, 30 * i}, (float)font.baseSize/16, 2, BLACK); DrawTextEx(font, segments->segments[i].name, (Vector2){10, 30 * i}, (float)font.baseSize/16, 2, WHITE);
DrawTextEx(font, time_unparse(buffer, 100, &segments->list[i]->realtime), (Vector2){200, 30 * i}, (float)font.baseSize/16, 2, BLACK); //DrawTextEx(font, time_unparse(buffer, 100, &segments->segments[i].realtime), (Vector2){200, 30 * i}, (float)font.baseSize/16, 2, BLACK);
} }
}*/
void debug_print_list(segment_list *segments) {
for (int i = 0; i < segments->count; i++) {
printf("fucker %d\n", i);
printf("%s\n", segments->segments[i].name);
}
} }
*/
//probably need a thing to free all the segments //probably need a thing to free all the segments

@ -0,0 +1,104 @@
#include "splits.h"
//#include "parser.h"
#include "timer.h"
#include "xml.h"
#include <math.h>
#include <raylib.h>
extern Font font;
extern void error(const char *msg);
void print_segment(segment *seg) {
printf("%s\n", seg->name);
//printf("%ld.%ld\n", seg->realtime.tv_sec, seg->realtime.tv_nsec);
}
/*struct timespec parse_time(char *str) {
struct timespec time;
time_t hour_t;
time_t min_t;
time_t sec_t;
time_t nsec_t;
sscanf(str, "%ld:%ld:%ld.%ld", &hour_t, &min_t, &sec_t, &nsec_t);
time.tv_sec = (hour_t * 3600) + (min_t * 60) + (sec_t);
time.tv_nsec = nsec_t * 1e+7f;
//printf("%lf\n", timespec_to_double(time));
//180.500_000_000
return time;
}*/
/*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) {
strftime(buffer, len, "%M:%S.", gmtime(&ts->tv_sec));
} 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));
}
double ns = timespec_to_double(*ts);
ns = ns - (long)ns;
snprintf(&buffer[strlen(buffer)], len, "%.2ld", (long)(ns*100));
return buffer;
}*/
//utils
int get_file_size(FILE *file) {
int size;
fseek(file, 0L, SEEK_END);
size = ftell(file);
fseek(file, 0L, SEEK_SET);
return size;
}
void log_node(struct xml_node *node) {
//struct xml_node *root = xml_document_root(document);
struct xml_string *string = xml_node_name(node);
int len = xml_string_length(string);
uint8_t *buffer = calloc(len + 1, sizeof(uint8_t));
xml_string_copy(string, buffer, len);
printf("%s\n", buffer);
free(buffer);
}
segment_list open_splits_file(const char *path) {
FILE *xml_file = fopen(path, "r");
if (!xml_file) {
error("Could not open file");
}
int xml_file_size = get_file_size(xml_file);
uint8_t *buffer = calloc(sizeof(uint8_t), xml_file_size);
fread(buffer, sizeof(uint8_t), xml_file_size, xml_file);
struct xml_document *xml = xml_parse_document(buffer, xml_file_size);
if (!xml) {
error("Could not parse xml");
}
printf("parsed %s successfully\n", path);
return (segment_list){0};
}
/*
void render_splits(segment_list *segments) {
char buffer[100];
for (int i = 0; i < segments->cnt; i++) {
DrawTextEx(font, segments->list[i]->name, (Vector2){10, 30 * i}, (float)font.baseSize/16, 2, BLACK);
DrawTextEx(font, time_unparse(buffer, 100, &segments->list[i]->realtime), (Vector2){200, 30 * i}, (float)font.baseSize/16, 2, BLACK);
}
}
*/
//probably need a thing to free all the segments

@ -11,15 +11,22 @@ struct segment {
struct timespec gametime; struct timespec gametime;
struct timespec best; struct timespec best;
char *name; char *name;
segment *next; //segment *next;
}; };
typedef struct segment_list { typedef struct segment_list {
segment **list; segment *segments;
int cnt; int count;
} segment_list; } segment_list;
//binds two lists of segments together
typedef struct segment_binder {
segment_list *rta;
segment_list *igt;
} segment_binder;
segment_list open_splits_file(const char *path); segment_list open_splits_file(const char *path);
void render_splits(segment_list *segments); void render_splits(segment_list *segments);
void debug_print_list(segment_list *segments);
#endif #endif

@ -20,8 +20,8 @@ double timespec_to_double(struct timespec ts) {
} }
GHTimer *ghtimer_new(void) { ghtimer *ghtimer_new(void) {
GHTimer *timer = calloc(1, sizeof(GHTimer)); ghtimer *timer = calloc(1, sizeof(ghtimer));
timer->running = false; timer->running = false;
timer->paused = false; timer->paused = false;
clock_gettime(CLOCK_REALTIME, &timer->pause_start); clock_gettime(CLOCK_REALTIME, &timer->pause_start);
@ -31,27 +31,27 @@ GHTimer *ghtimer_new(void) {
return timer; return timer;
} }
inline void ghtimer_delete(GHTimer *timer) { inline void ghtimer_delete(ghtimer *timer) {
free(timer); free(timer);
} }
void ghtimer_start(GHTimer *timer) { void ghtimer_start(ghtimer *timer) {
clock_gettime(CLOCK_REALTIME, &timer->start); clock_gettime(CLOCK_REALTIME, &timer->start);
timer->running = true; timer->running = true;
} }
void ghtimer_pause(GHTimer *timer) { void ghtimer_pause(ghtimer *timer) {
clock_gettime(CLOCK_REALTIME, &timer->pause_start); clock_gettime(CLOCK_REALTIME, &timer->pause_start);
timer->paused = true; timer->paused = true;
} }
void ghtimer_resume(GHTimer *timer) { void ghtimer_resume(ghtimer *timer) {
struct timespec t = subts(timer->pause_current, timer->pause_start); struct timespec t = subts(timer->pause_current, timer->pause_start);
timer->diff = addts(timer->diff, t); timer->diff = addts(timer->diff, t);
timer->paused = false; timer->paused = false;
} }
void ghtimer_stop(GHTimer *timer) { void ghtimer_stop(ghtimer *timer) {
timer->running = false; timer->running = false;
timer->paused = false; timer->paused = false;
clock_gettime(CLOCK_REALTIME, &timer->pause_start); clock_gettime(CLOCK_REALTIME, &timer->pause_start);
@ -61,13 +61,13 @@ void ghtimer_stop(GHTimer *timer) {
timer->diff = (struct timespec) {0}; timer->diff = (struct timespec) {0};
} }
void ghtimer_reset(GHTimer *timer) { void ghtimer_reset(ghtimer *timer) {
timer->running = false; timer->running = false;
timer->start = (struct timespec) {0}; timer->start = (struct timespec) {0};
timer->current = timer->start; timer->current = timer->start;
} }
void ghtimer_tick(GHTimer *timer) { void ghtimer_tick(ghtimer *timer) {
if (!timer->running) { if (!timer->running) {
return; return;
} }
@ -79,13 +79,49 @@ void ghtimer_tick(GHTimer *timer) {
} }
} }
struct timespec ghtimer_time(GHTimer *timer) { struct timespec ghtimer_time(ghtimer *timer) {
struct timespec time = subts(timer->current, timer->start); struct timespec time = subts(timer->current, timer->start);
return subts(time, timer->diff); return subts(time, timer->diff);
} }
void ghtimer_timestring(GHTimer *timer, char *buffer) { void ghtimer_timestring(ghtimer *timer, char *buffer) {
struct timespec time = ghtimer_time(timer); struct timespec time = ghtimer_time(timer);
double dbl = timespec_to_double(time); double dbl = timespec_to_double(time);
sprintf(buffer, "%.02lf", dbl); sprintf(buffer, "%.02lf", dbl);
} }
ghost ghost_new(void) {
return (ghost) {
.rta = ghtimer_new(),
.igt = ghtimer_new()
};
}
ghost ghost_rta_new(void) {
return (ghost) {
.rta = ghtimer_new(),
NULL
};
}
//free and set to NULL
void ghost_delete(ghost ghost) {
ghtimer_delete(ghost.rta);
ghtimer_delete(ghost.igt);
ghost.rta = NULL;
ghost.igt = NULL;
}
void ghost_tick(ghost ghost) {
ghtimer_tick(ghost.rta);
if (ghost.igt == NULL)
return;
ghtimer_tick(ghost.igt);
}
void ghost_start(ghost ghost) {
ghtimer_start(ghost.rta);
ghtimer_start(ghost.igt);
}

@ -15,7 +15,7 @@ double timespec_to_double(struct timespec ts);
//appended GH just incase theres a conflict with anything //appended GH just incase theres a conflict with anything
//else named "Timer" //else named "Timer"
typedef struct GHTimer { typedef struct ghtimer {
struct timespec start; struct timespec start;
struct timespec current; struct timespec current;
struct timespec pause_start; struct timespec pause_start;
@ -23,18 +23,30 @@ typedef struct GHTimer {
struct timespec diff; struct timespec diff;
int running; int running;
int paused; int paused;
} GHTimer; } ghtimer;
GHTimer *ghtimer_new(void); //two timers tied together
void ghtimer_delete(GHTimer *timer); typedef struct ghost {
void ghtimer_start(GHTimer *timer); ghtimer *rta;
void ghtimer_pause(GHTimer *timer); ghtimer *igt;
void ghtimer_resume(GHTimer *timer); } ghost;
void ghtimer_stop(GHTimer *timer);
void ghtimer_reset(GHTimer *timer); ghtimer *ghtimer_new(void);
void ghtimer_tick(GHTimer *timer); void ghtimer_delete(ghtimer *timer);
void ghtimer_start(ghtimer *timer);
struct timespec ghtimer_time(GHTimer *timer); void ghtimer_pause(ghtimer *timer);
void ghtimer_timestring(GHTimer *timer, char *buffer); void ghtimer_resume(ghtimer *timer);
void ghtimer_stop(ghtimer *timer);
void ghtimer_reset(ghtimer *timer);
void ghtimer_tick(ghtimer *timer);
struct timespec ghtimer_time(ghtimer *timer);
void ghtimer_timestring(ghtimer *timer, char *buffer);
ghost ghost_new(void);
ghost ghost_rta_new(void);
void ghost_delete(ghost ghost); //free and set to NULL
void ghost_tick(ghost ghost);
void ghost_start(ghost ghost);
#endif #endif

@ -1,6 +1,6 @@
#include "timer_renderer.h" #include "timer_renderer.h"
timer_renderer *create_timer_renderer(GHTimer *t, Vector2 p, Vector2 sz) { timer_renderer *create_timer_renderer(ghost t, Vector2 p, Vector2 sz) {
timer_renderer *tr = calloc(1, sizeof(timer_renderer)); timer_renderer *tr = calloc(1, sizeof(timer_renderer));
tr->timer = t; tr->timer = t;
tr->pos = p; tr->pos = p;
@ -22,7 +22,7 @@ void destroy_timer_renderer(timer_renderer *tr) {
} }
void render_timer(timer_renderer *tr) { void render_timer(timer_renderer *tr) {
struct timespec ts = ghtimer_time(tr->timer); struct timespec ts = ghtimer_time(tr->mode ? tr->timer.igt : tr->timer.rta);
time_unparse(tr->strfmt, FMT_SIZE, &ts); time_unparse(tr->strfmt, FMT_SIZE, &ts);
Vector2 text_size = MeasureTextEx(font, tr->strfmt, (float)font.baseSize/4, 2); Vector2 text_size = MeasureTextEx(font, tr->strfmt, (float)font.baseSize/4, 2);
@ -32,11 +32,11 @@ void render_timer(timer_renderer *tr) {
} }
//draw the timer background //draw the timer background
DrawRectangle(tr->pos.x, tr->pos.y, tr->size.x, tr->size.y, WHITE); DrawRectangle(tr->pos.x, tr->pos.y, tr->size.x, tr->size.y, BLACK);
if (tr->shader != NULL) { if (tr->shader != NULL) {
EndShaderMode(); EndShaderMode();
} }
DrawTextEx(font, tr->strfmt , (Vector2){(float)windowWidth - text_size.x - 2.0f, tr->pos.y}, (float)font.baseSize / 4, 2, BLACK); DrawTextEx(font, tr->strfmt , (Vector2){(float)windowWidth - text_size.x - 2.0f, tr->pos.y}, (float)font.baseSize / 4, 2, WHITE);
} }

@ -15,8 +15,14 @@ extern int windowHeight;
extern char *time_unparse(char *buffer, size_t len, struct timespec *ts); extern char *time_unparse(char *buffer, size_t len, struct timespec *ts);
#define FMT_SIZE 64 #define FMT_SIZE 64
enum mode {
RTA = 0,
IGT = 1,
};
typedef struct timer_renderer { typedef struct timer_renderer {
GHTimer *timer; ghost timer;
int mode;
Font font; Font font;
Vector2 pos; Vector2 pos;
Vector2 size; Vector2 size;
@ -25,7 +31,7 @@ typedef struct timer_renderer {
char strfmt[FMT_SIZE]; char strfmt[FMT_SIZE];
} timer_renderer; } timer_renderer;
timer_renderer *create_timer_renderer(GHTimer *t, Vector2 p, Vector2 sz); timer_renderer *create_timer_renderer(ghost t, Vector2 p, Vector2 sz);
void set_timer_shader(timer_renderer *tr, Shader *s); void set_timer_shader(timer_renderer *tr, Shader *s);
void set_timer_pos(timer_renderer *tr, Vector2 p); void set_timer_pos(timer_renderer *tr, Vector2 p);
//maybe just destroy_renderer() or just free() //maybe just destroy_renderer() or just free()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,196 @@
/**
* Copyright (c) 2012 ooxi/xml.c
* https://github.com/ooxi/xml.c
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef HEADER_XML
#define HEADER_XML
/**
* Includes
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Opaque structure holding the parsed xml document
*/
struct xml_document;
struct xml_node;
struct xml_attribute;
/**
* Internal character sequence representation
*/
struct xml_string;
/**
* Tries to parse the XML fragment in buffer
*
* @param buffer Chunk to parse
* @param length Size of the buffer
*
* @warning `buffer` will be referenced by the document, you may not free it
* until you free the xml_document
* @warning You have to call xml_document_free after you finished using the
* document
*
* @return The parsed xml fragment iff parsing was successful, 0 otherwise
*/
struct xml_document* xml_parse_document(uint8_t* buffer, size_t length);
/**
* Tries to read an XML document from disk
*
* @param source File that will be read into an xml document. Will be closed
*
* @warning You have to call xml_document_free with free_buffer = true after you
* finished using the document
*
* @return The parsed xml fragment iff parsing was successful, 0 otherwise
*/
struct xml_document* xml_open_document(FILE* source);
/**
* Frees all resources associated with the document. All xml_node and xml_string
* references obtained through the document will be invalidated
*
* @param document xml_document to free
* @param free_buffer iff true the internal buffer supplied via xml_parse_buffer
* will be freed with the `free` system call
*/
void xml_document_free(struct xml_document* document, bool free_buffer);
/**
* @return xml_node representing the document root
*/
struct xml_node* xml_document_root(struct xml_document* document);
/**
* @return The xml_node's tag name
*/
struct xml_string* xml_node_name(struct xml_node* node);
/**
* @return The xml_node's string content (if available, otherwise NULL)
*/
struct xml_string* xml_node_content(struct xml_node* node);
/**
* @return Number of child nodes
*/
size_t xml_node_children(struct xml_node* node);
/**
* @return The n-th child or 0 if out of range
*/
struct xml_node* xml_node_child(struct xml_node* node, size_t child);
/**
* @return Number of attribute nodes
*/
size_t xml_node_attributes(struct xml_node* node);
/**
* @return the n-th attribute name or 0 if out of range
*/
struct xml_string* xml_node_attribute_name(struct xml_node* node, size_t attribute);
/**
* @return the n-th attribute content or 0 if out of range
*/
struct xml_string* xml_node_attribute_content(struct xml_node* node, size_t attribute);
/**
* @return The node described by the path or 0 if child cannot be found
* @warning Each element on the way must be unique
* @warning Last argument must be 0
*/
struct xml_node* xml_easy_child(struct xml_node* node, uint8_t const* child, ...);
/**
* @return 0-terminated copy of node name
* @warning User must free the result
*/
uint8_t* xml_easy_name(struct xml_node* node);
/**
* @return 0-terminated copy of node content
* @warning User must free the result
*/
uint8_t* xml_easy_content(struct xml_node* node);
/**
* @return Length of the string
*/
size_t xml_string_length(struct xml_string* string);
/**
* Copies the string into the supplied buffer
*
* @warning String will not be 0-terminated
* @warning Will write at most length bytes, even if the string is longer
*/
void xml_string_copy(struct xml_string* string, uint8_t* buffer, size_t length);
#ifdef __cplusplus
}
#endif
#endif

2076
test.xml

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save