Merge pull request #1197 from tsoding/cleanup

Cleanup
master
Alexey Kutepov 2019-12-11 20:59:27 +07:00 committed by GitHub
commit 69bc08cdde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 170 additions and 501 deletions

View File

@ -22,4 +22,10 @@
#define CAMERA_RATIO_X 16.0f
#define CAMERA_RATIO_Y 9.0f
#define METADATA_TITLE_MAX_SIZE 256
#define METADATA_VERSION_MAX_SIZE 256
#define METADATA_FILEPATH_MAX_SIZE 512
#define VERSION "1"
#endif // CONFIG_H_

View File

@ -9,7 +9,7 @@
#define DYNARRAY_INIT_CAPACITY 8
void *dynarray_pointer_at(Dynarray *dynarray, size_t index)
void *dynarray_pointer_at(const Dynarray *dynarray, size_t index)
{
trace_assert(index < dynarray->count);
return (uint8_t *)dynarray->data + index * dynarray->element_size;

View File

@ -24,7 +24,7 @@ Dynarray create_dynarray(size_t element_size)
return result;
}
void *dynarray_pointer_at(Dynarray *dynarray, size_t index);
void *dynarray_pointer_at(const Dynarray *dynarray, size_t index);
void dynarray_replace_at(Dynarray *dynarray, size_t index, void *element);
void dynarray_copy_to(Dynarray *dynarray, void *dest, size_t index);
void dynarray_clear(Dynarray *dynarray);

View File

@ -6,8 +6,6 @@
#include "color.h"
#include "game/camera.h"
typedef struct LineStream LineStream;
typedef struct {
Color base_color;
} Background;

View File

@ -7,7 +7,6 @@
typedef struct Boxes Boxes;
typedef struct Player Player;
typedef struct LineStream LineStream;
typedef struct Player Player;
typedef struct RectLayer RectLayer;

View File

@ -35,83 +35,6 @@ struct Goals {
float angle;
};
Goals *create_goals_from_line_stream(LineStream *line_stream)
{
trace_assert(line_stream);
Lt *lt = create_lt();
Goals *const goals = PUSH_LT(lt, nth_calloc(1, sizeof(Goals)), free);
if (goals == NULL) {
RETURN_LT(lt, NULL);
}
goals->count = 0;
if (sscanf(
line_stream_next(line_stream),
"%zu",
&goals->count) == EOF) {
log_fail("Could not read amount of goals\n");
RETURN_LT(lt, NULL);
}
goals->ids = PUSH_LT(
lt,
nth_calloc(1, sizeof(char*) * goals->count),
free);
if (goals->ids == NULL) {
RETURN_LT(lt, NULL);
}
for (size_t i = 0; i < goals->count; ++i) {
goals->ids[i] = PUSH_LT(lt, nth_calloc(1, sizeof(char) * ENTITY_MAX_ID_SIZE), free);
if (goals->ids[i] == NULL) {
RETURN_LT(lt, NULL);
}
}
goals->positions = PUSH_LT(lt, nth_calloc(1, sizeof(Vec2f) * goals->count), free);
if (goals->positions == NULL) {
RETURN_LT(lt, NULL);
}
goals->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * goals->count), free);
if (goals->colors == NULL) {
RETURN_LT(lt, NULL);
}
goals->cue_states = PUSH_LT(lt, nth_calloc(1, sizeof(int) * goals->count), free);
if (goals->cue_states == NULL) {
RETURN_LT(lt, NULL);
}
goals->visible = PUSH_LT(lt, nth_calloc(1, sizeof(bool) * goals->count), free);
if (goals->visible == NULL) {
RETURN_LT(lt, NULL);
}
char color[7];
for (size_t i = 0; i < goals->count; ++i) {
if (sscanf(
line_stream_next(line_stream),
"%" STRINGIFY(ENTITY_MAX_ID_SIZE) "s%f%f%6s",
goals->ids[i],
&goals->positions[i].x,
&goals->positions[i].y,
color) < 0) {
log_fail("Could not read %dth goal\n", i);
RETURN_LT(lt, NULL);
}
goals->colors[i] = hexstr(color);
goals->cue_states[i] = CUE_STATE_VIRGIN;
goals->visible[i] = true;
}
goals->lt = lt;
goals->angle = 0.0f;
return goals;
}
Goals *create_goals_from_point_layer(const PointLayer *point_layer)
{
trace_assert(point_layer);

View File

@ -9,10 +9,8 @@
#include "config.h"
typedef struct Goals Goals;
typedef struct LineStream LineStream;
typedef struct PointLayer PointLayer;
Goals *create_goals_from_line_stream(LineStream *line_stream);
Goals *create_goals_from_point_layer(const PointLayer *point_layer);
void destroy_goals(Goals *goals);

View File

@ -34,96 +34,6 @@ struct Labels
enum LabelState *states;
};
Labels *create_labels_from_line_stream(LineStream *line_stream)
{
trace_assert(line_stream);
Lt *lt = create_lt();
Labels * const labels = PUSH_LT(lt, nth_calloc(1, sizeof(Labels)), free);
if (labels == NULL) {
RETURN_LT(lt, NULL);
}
labels->lt = lt;
if (sscanf(
line_stream_next(line_stream),
"%zu",
&labels->count) == EOF) {
log_fail("Could not read amount of labels\n");
RETURN_LT(lt, NULL);
}
labels->ids = PUSH_LT(lt, nth_calloc(labels->count, sizeof(char) * ENTITY_MAX_ID_SIZE), free);
if (labels->ids == NULL) {
RETURN_LT(lt, NULL);
}
labels->positions = PUSH_LT(lt, nth_calloc(1, sizeof(Vec2f) * labels->count), free);
if (labels->positions == NULL) {
RETURN_LT(lt, NULL);
}
labels->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * labels->count), free);
if (labels->colors == NULL) {
RETURN_LT(lt, NULL);
}
labels->texts = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
if (labels->texts == NULL) {
RETURN_LT(lt, NULL);
}
labels->alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
if (labels->alphas == NULL) {
RETURN_LT(lt, NULL);
}
labels->delta_alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
if (labels->delta_alphas == NULL) {
RETURN_LT(lt, NULL);
}
labels->states = PUSH_LT(lt, nth_calloc(1, sizeof(enum LabelState) * labels->count), free);
if (labels->states == NULL) {
RETURN_LT(lt, NULL);
}
char color[7];
for (size_t i = 0; i < labels->count; ++i) {
if (sscanf(
line_stream_next(line_stream),
"%" STRINGIFY(ENTITY_MAX_ID_SIZE) "s%f%f%6s\n",
labels->ids + i * ENTITY_MAX_ID_SIZE,
&labels->positions[i].x,
&labels->positions[i].y,
color) == EOF) {
log_fail("Could not read position and color of %dth label\n", i);
RETURN_LT(lt, NULL);
}
labels->colors[i] = hexstr(color);
const char *label_text = line_stream_next(line_stream);
if (label_text == NULL) {
log_fail("Could not read text of %dth label\n", i);
RETURN_LT(lt, NULL);
}
labels->texts[i] = PUSH_LT(
lt,
string_duplicate(label_text, NULL),
free);
if (labels->texts[i] == NULL) {
RETURN_LT(lt, NULL);
}
trim_endline(labels->texts[i]);
}
return labels;
}
Labels *create_labels_from_label_layer(const LabelLayer *label_layer)
{
trace_assert(label_layer);

View File

@ -6,10 +6,8 @@
#include "config.h"
typedef struct Labels Labels;
typedef struct LineStream LineStream;
typedef struct LabelLayer LabelLayer;
Labels *create_labels_from_line_stream(LineStream *line_stream);
Labels *create_labels_from_label_layer(const LabelLayer *label_layer);
void destroy_labels(Labels *label);

View File

@ -20,42 +20,6 @@ struct Lava {
Wavy_rect **rects;
};
Lava *create_lava_from_line_stream(LineStream *line_stream)
{
trace_assert(line_stream);
Lt *lt = create_lt();
Lava *lava = PUSH_LT(lt, nth_calloc(1, sizeof(Lava)), free);
if (lava == NULL) {
RETURN_LT(lt, NULL);
}
if (sscanf(
line_stream_next(line_stream),
"%zu",
&lava->rects_count) < 0) {
log_fail("Could not read amount of lava\n");
RETURN_LT(lt, NULL);
}
lava->rects = PUSH_LT(lt, nth_calloc(1, sizeof(Wavy_rect*) * lava->rects_count), free);
if (lava->rects == NULL) {
RETURN_LT(lt, NULL);
}
for (size_t i = 0; i < lava->rects_count; ++i) {
lava->rects[i] = PUSH_LT(lt, create_wavy_rect_from_line_stream(line_stream), destroy_wavy_rect);
if (lava->rects[i] == NULL) {
RETURN_LT(lt, NULL);
}
}
lava->lt = lt;
return lava;
}
Lava *create_lava_from_rect_layer(const RectLayer *rect_layer)
{
Lt *lt = create_lt();

View File

@ -8,10 +8,8 @@
#include "math/rect.h"
typedef struct Lava Lava;
typedef struct LineStream LineStream;
typedef struct RectLayer RectLayer;
Lava *create_lava_from_line_stream(LineStream *line_stream);
Lava *create_lava_from_rect_layer(const RectLayer *rect_layer);
void destroy_lava(Lava *lava);

View File

@ -39,27 +39,6 @@ Wavy_rect *create_wavy_rect(Rect rect, Color color)
return wavy_rect;
}
Wavy_rect *create_wavy_rect_from_line_stream(LineStream *line_stream)
{
trace_assert(line_stream);
char color_name[7];
Rect rect;
if (sscanf(
line_stream_next(line_stream),
"%f%f%f%f%6s\n",
&rect.x, &rect.y,
&rect.w, &rect.h,
color_name) < 0) {
log_fail("Could not read a wavy rect\n");
return NULL;
}
Color color = hexstr(color_name);
return create_wavy_rect(rect, color);
}
void destroy_wavy_rect(Wavy_rect *wavy_rect)
{
trace_assert(wavy_rect);

View File

@ -8,10 +8,8 @@
#include "math/rect.h"
typedef struct Wavy_rect Wavy_rect;
typedef struct LineStream LineStream;
Wavy_rect *create_wavy_rect(Rect rect, Color color);
Wavy_rect *create_wavy_rect_from_line_stream(LineStream *line_stream);
void destroy_wavy_rect(Wavy_rect *wavy_rect);
int wavy_rect_render(const Wavy_rect *wavy_rect,

View File

@ -63,12 +63,12 @@ LevelEditor *create_level_editor(Cursor *cursor)
memset(level_editor->metadata.version, 0, METADATA_VERSION_MAX_SIZE);
memcpy(level_editor->metadata.version,
VERSION,
min_size_t(sizeof(VERSION), METADATA_VERSION_MAX_SIZE - 1));
MIN(size_t, sizeof(VERSION), METADATA_VERSION_MAX_SIZE - 1));
memset(level_editor->metadata.title, 0, METADATA_TITLE_MAX_SIZE);
memcpy(level_editor->metadata.title,
DEFAULT_LEVEL_TITLE,
min_size_t(sizeof(DEFAULT_LEVEL_TITLE), METADATA_TITLE_MAX_SIZE - 1));
MIN(size_t, sizeof(DEFAULT_LEVEL_TITLE), METADATA_TITLE_MAX_SIZE - 1));
level_editor->background_layer = create_background_layer(hexstr("fffda5"));
@ -196,7 +196,7 @@ LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor
RETURN_LT(lt, NULL);
}
if (metadata_load_from_line_stream(&level_editor->metadata, level_stream) < 0) {
if (metadata_load_from_line_stream(&level_editor->metadata, level_stream, level_editor->file_name) < 0) {
RETURN_LT(lt, NULL);
}

View File

@ -7,7 +7,6 @@
#include "math/rect.h"
typedef struct Platforms Platforms;
typedef struct LineStream LineStream;
typedef struct RectLayer RectLayer;
Platforms *create_platforms_from_rect_layer(const RectLayer *layer);

View File

@ -12,7 +12,6 @@
typedef struct Player Player;
typedef struct Goals Goals;
typedef struct LineStream LineStream;
typedef struct RigidBodies RigidBodies;
Player *create_player_from_player_layer(const PlayerLayer *player_layer,

View File

@ -6,7 +6,6 @@
typedef struct Regions Regions;
typedef struct Player Player;
typedef struct LineStream LineStream;
typedef struct Level Level;
typedef struct RectLayer RectLayer;
typedef struct Labels Labels;

View File

@ -5,7 +5,6 @@
typedef struct RigidBodies RigidBodies;
typedef struct Platforms Platforms;
typedef struct LineStream LineStream;
typedef size_t RigidBodyId;

View File

@ -15,102 +15,40 @@
#include "./level_folder.h"
#define LEVEL_FOLDER_MAX_LENGTH 512
struct LevelFolder
void level_folder_read(const char *dirpath, LevelFolder *folder)
{
Lt *lt;
Dynarray filenames;
Dynarray titles;
};
LevelFolder *create_level_folder(const char *dirpath)
{
trace_assert(dirpath);
Lt *lt = create_lt();
LevelFolder *level_folder = PUSH_LT(
lt,
nth_calloc(1, sizeof(LevelFolder)),
free);
if (level_folder == NULL) {
RETURN_LT(lt, NULL);
DIR *level_dir = opendir(dirpath);
if (level_dir == NULL) {
log_fail("Can't open asset folder: %s\n", dirpath);
abort();
}
level_folder->lt = lt;
level_folder->filenames = create_dynarray(sizeof(const char*));
level_folder->titles = create_dynarray(sizeof(const char*));
dynarray_clear(&folder->metadatas);
char path[LEVEL_FOLDER_MAX_LENGTH];
DIR *level_dir = PUSH_LT(lt, opendir(dirpath), closedir_lt);
LevelMetadata level_metadata;
char filepath[METADATA_FILEPATH_MAX_SIZE];
LevelMetadata metadata;
for (struct dirent *d = readdir(level_dir);
d != NULL;
d = readdir(level_dir)) {
if (*d->d_name == '.') {
if (*d->d_name == '.') continue;
snprintf(filepath, METADATA_FILEPATH_MAX_SIZE,
"%s/%s", dirpath, d->d_name);
if (metadata_load_from_file(&metadata, filepath) < 0) {
log_warn("Can't read level: %s\n", filepath);
continue;
}
snprintf(path, LEVEL_FOLDER_MAX_LENGTH, "%s/%s", dirpath, d->d_name);
const char *filepath = PUSH_LT(lt, string_duplicate(trim_endline(path), NULL), free);
if (filepath == NULL) {
RETURN_LT(lt, NULL);
}
if (metadata_load_from_file(&level_metadata, filepath) < 0) {
RETURN_LT(lt, NULL);
}
const char *version = PUSH_LT(
lt,
string_duplicate(level_metadata.version, NULL),
free);
const char *title = PUSH_LT(
lt,
string_duplicate(level_metadata.title, NULL),
free);
if(strcmp(version, VERSION) == 0) {
dynarray_push(&level_folder->titles, &title);
dynarray_push(&level_folder->filenames, &filepath);
} else {
log_info(
if(strcmp(metadata.version, VERSION) != 0) {
log_warn(
"Unsupported version for level [%s]: Expected `%s`, got `%s`\n",
d->d_name,
VERSION,
version);
filepath, VERSION, metadata.version);
continue;
}
dynarray_push(&folder->metadatas, &metadata);
}
closedir(RELEASE_LT(lt, level_dir));
return level_folder;
}
void destroy_level_folder(LevelFolder *level_folder)
{
trace_assert(level_folder);
free(level_folder->filenames.data);
free(level_folder->titles.data);
RETURN_LT0(level_folder->lt);
}
const char **level_folder_filenames(const LevelFolder *level_folder)
{
trace_assert(level_folder);
return (const char **)level_folder->filenames.data;
}
const char **level_folder_titles(const LevelFolder *level_folder)
{
trace_assert(level_folder);
return (const char **)level_folder->titles.data;
}
size_t level_folder_count(const LevelFolder *level_folder)
{
trace_assert(level_folder);
return level_folder->filenames.count;
closedir(level_dir);
}

View File

@ -1,13 +1,27 @@
#ifndef LEVEL_FOLDER_H_
#define LEVEL_FOLDER_H_
typedef struct LevelFolder LevelFolder;
#include "level_metadata.h"
LevelFolder *create_level_folder(const char *dirpath);
void destroy_level_folder(LevelFolder *level_folder);
typedef struct {
Dynarray metadatas;
} LevelFolder;
const char **level_folder_filenames(const LevelFolder *level_folder);
const char **level_folder_titles(const LevelFolder *level_folder);
size_t level_folder_count(const LevelFolder *level_folder);
static inline
LevelFolder create_level_folder(void)
{
LevelFolder result = {
.metadatas = create_dynarray(sizeof(LevelMetadata)),
};
return result;
}
static inline
void destroy_level_folder(LevelFolder level_folder)
{
free(level_folder.metadatas.data);
}
void level_folder_read(const char *dirpath, LevelFolder *folder);
#endif // LEVEL_FOLDER_H_

View File

@ -9,21 +9,16 @@
#include "level_metadata.h"
#include "math/extrema.h"
struct LevelMetadata
{
Lt *lt;
const char *version;
const char *title;
};
int metadata_load_from_line_stream(LevelMetadata *metadata,
LineStream *line_stream)
LineStream *line_stream,
const char *filepath)
{
trace_assert(metadata);
trace_assert(line_stream);
memset(metadata->version, 0, METADATA_VERSION_MAX_SIZE);
memset(metadata->title, 0, METADATA_TITLE_MAX_SIZE);
memset(metadata->filepath, 0, METADATA_FILEPATH_MAX_SIZE);
const char *line = line_stream_next(line_stream);
if (line == NULL) return -1;
@ -41,18 +36,23 @@ int metadata_load_from_line_stream(LevelMetadata *metadata,
min_size_t(strlen(line), METADATA_VERSION_MAX_SIZE - 1));
trim_endline(metadata->title);
memcpy(metadata->filepath,
filepath,
min_size_t(strlen(filepath), METADATA_FILEPATH_MAX_SIZE - 1));
trim_endline(metadata->filepath);
return 0;
}
int metadata_load_from_file(LevelMetadata *metadata, const char *filename)
int metadata_load_from_file(LevelMetadata *metadata, const char *filepath)
{
trace_assert(metadata);
trace_assert(filename);
trace_assert(filepath);
LineStream *line_stream = create_line_stream(filename, "r", 256);
LineStream *line_stream = create_line_stream(filepath, "r", 256);
if (line_stream == NULL) return -1;
int err = metadata_load_from_line_stream(metadata, line_stream);
int err = metadata_load_from_line_stream(metadata, line_stream, filepath);
destroy_line_stream(line_stream);
return err;
}

View File

@ -1,19 +1,17 @@
#ifndef LEVEL_METADATA_H_
#define LEVEL_METADATA_H_
#include "config.h"
typedef struct LineStream LineStream;
#define VERSION "1"
#define METADATA_TITLE_MAX_SIZE 256
#define METADATA_VERSION_MAX_SIZE 256
typedef struct {
char filepath[METADATA_FILEPATH_MAX_SIZE];
char version[METADATA_VERSION_MAX_SIZE];
char title[METADATA_TITLE_MAX_SIZE];
} LevelMetadata;
int metadata_load_from_file(LevelMetadata *metadata, const char *file);
int metadata_load_from_line_stream(LevelMetadata *metadata, LineStream *line_stream);
int metadata_load_from_file(LevelMetadata *metadata, const char *filepath);
int metadata_load_from_line_stream(LevelMetadata *metadata, LineStream *line_stream, const char *filepath);
#endif // LEVEL_METADATA_H_

View File

@ -21,11 +21,18 @@ struct LevelPicker
Lt *lt;
Background background;
Vec2f camera_position;
LevelFolder *level_folder;
LevelFolder level_folder;
WigglyText wiggly_text;
ListSelector *list_selector;
ListSelector list_selector;
};
static inline
const char *list_item_text(void *element)
{
trace_assert(element);
return ((LevelMetadata *)element)->title;
}
LevelPicker *create_level_picker(const char *dirpath)
{
trace_assert(dirpath);
@ -45,13 +52,8 @@ LevelPicker *create_level_picker(const char *dirpath)
level_picker->camera_position = vec(0.0f, 0.0f);
level_picker->level_folder = PUSH_LT(
lt,
create_level_folder(dirpath),
destroy_level_folder);
if (level_picker->level_folder == NULL) {
RETURN_LT(lt, NULL);
}
level_picker->level_folder = create_level_folder();
level_folder_read("./assets/levels", &level_picker->level_folder);
level_picker->wiggly_text = (WigglyText) {
.text = "Select Level",
@ -59,17 +61,10 @@ LevelPicker *create_level_picker(const char *dirpath)
.color = COLOR_WHITE,
};
level_picker->list_selector = PUSH_LT(
lt,
create_list_selector(
level_folder_titles(level_picker->level_folder),
level_folder_count(level_picker->level_folder),
vec(5.0f, 5.0f),
50.0f),
destroy_list_selector);
if (level_picker->list_selector == NULL) {
RETURN_LT(lt, NULL);
}
level_picker->list_selector.items = level_picker->level_folder.metadatas;
level_picker->list_selector.font_scale = vec(5.0f, 5.0f);
level_picker->list_selector.padding_bottom = 50.0f;
level_picker->list_selector.list_item_text = list_item_text;
return level_picker;
}
@ -77,6 +72,7 @@ LevelPicker *create_level_picker(const char *dirpath)
void destroy_level_picker(LevelPicker *level_picker)
{
trace_assert(level_picker);
destroy_level_folder(level_picker->level_folder);
RETURN_LT0(level_picker->lt);
}
@ -98,9 +94,7 @@ int level_picker_render(const LevelPicker *level_picker,
camera,
vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP));
if (list_selector_render(camera, level_picker->list_selector) < 0) {
return -1;
}
list_selector_render(camera, &level_picker->list_selector);
{
/* CSS */
@ -156,20 +150,19 @@ int level_picker_event(LevelPicker *level_picker,
const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
const Vec2f selector_size = list_selector_size(
level_picker->list_selector,
&level_picker->list_selector,
font_scale,
padding_bottom);
list_selector_move(
level_picker->list_selector,
level_picker->list_selector.position =
vec((float)width * 0.5f - selector_size.x * 0.5f,
TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM));
TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM);
} break;
}
} break;
}
return list_selector_event(level_picker->list_selector, event);
return list_selector_event(&level_picker->list_selector, event);
}
int level_picker_input(LevelPicker *level_picker,
@ -186,20 +179,21 @@ const char *level_picker_selected_level(const LevelPicker *level_picker)
{
trace_assert(level_picker);
const int selected_index = list_selector_selected(level_picker->list_selector);
if (selected_index < 0) {
if (level_picker->list_selector.selected_item < 0) {
return NULL;
}
const char **filenames = level_folder_filenames(level_picker->level_folder);
LevelMetadata *metadata = dynarray_pointer_at(
&level_picker->level_folder.metadatas,
(size_t)level_picker->list_selector.selected_item);
return filenames[selected_index];
return metadata->filepath;
}
void level_picker_clean_selection(LevelPicker *level_picker)
{
trace_assert(level_picker);
list_selector_clean_selection(level_picker->list_selector);
level_picker->list_selector.selected_item = -1;
}
int level_picker_enter_camera_event(LevelPicker *level_picker,

View File

@ -233,7 +233,7 @@ int main(int argc, char *argv[])
}
const int64_t end_frame_time = (int64_t) SDL_GetTicks();
SDL_Delay((unsigned int) max_int64(10, delta_time - (end_frame_time - begin_frame_time)));
SDL_Delay((unsigned int) MAX(int64_t, 10, delta_time - (end_frame_time - begin_frame_time)));
}
RETURN_LT(lt, 0);

View File

@ -3,25 +3,24 @@
#include <stdint.h>
// WARNING! Any attempts to "generalize" or "improve" this translation
// unit will result in an instantly closed Pull Request without any
// further discussion.
static inline
int64_t max_int64(int64_t a, int64_t b)
{
return a > b ? a : b;
}
#define MAX_INSTANCE(type) \
static inline \
type max_##type(type a, type b) { \
return a > b ? a : b; \
} \
static inline
size_t max_size_t(size_t a, size_t b)
{
return a > b ? a : b;
}
MAX_INSTANCE(int64_t)
MAX_INSTANCE(size_t)
#define MAX(type, a, b) max_##type(a, b)
static inline
size_t min_size_t(size_t a, size_t b)
{
return a < b ? a : b;
}
#define MIN_INSTANCE(type) \
static inline \
type min_##type(type a, type b) { \
return a < b ? a : b; \
} \
MIN_INSTANCE(int64_t)
MIN_INSTANCE(size_t)
#define MIN(type, a, b) min_##type(a, b)
#endif // EXTREMA_H_

View File

@ -13,49 +13,6 @@
#include "./list_selector.h"
struct ListSelector
{
Lt *lt;
const char **items;
size_t count;
size_t cursor;
int selected_item;
Vec2f position;
Vec2f font_scale;
float padding_bottom;
};
ListSelector *create_list_selector(const char *items[],
size_t count,
Vec2f font_scale,
float padding_bottom)
{
trace_assert(items);
Lt *lt = create_lt();
ListSelector *list_selector = PUSH_LT(lt, nth_calloc(1, sizeof(ListSelector)), free);
if (list_selector == NULL) {
RETURN_LT(lt, NULL);
}
list_selector->lt = lt;
list_selector->items = items;
list_selector->count = count;
list_selector->cursor = 0;
list_selector->selected_item = -1;
list_selector->position = vec(0.0f, 0.0f);
list_selector->font_scale = font_scale;
list_selector->padding_bottom = padding_bottom;
return list_selector;
}
void destroy_list_selector(ListSelector *list_selector)
{
trace_assert(list_selector);
RETURN_LT0(list_selector->lt);
}
int list_selector_render(const Camera *camera,
const ListSelector *list_selector)
@ -63,25 +20,31 @@ int list_selector_render(const Camera *camera,
trace_assert(camera);
trace_assert(list_selector);
for (size_t i = 0; i < list_selector->count; ++i) {
for (size_t i = 0; i < list_selector->items.count; ++i) {
const Vec2f current_position = vec_sum(
list_selector->position,
vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
const char *item_text =
list_selector->list_item_text(
dynarray_pointer_at(
&list_selector->items,
i));
sprite_font_render_text(
&camera->font,
camera->renderer,
current_position,
list_selector->font_scale,
rgba(1.0f, 1.0f, 1.0f, 1.0f),
list_selector->items[i]);
item_text);
if (i == list_selector->cursor) {
SDL_Rect boundary_box = rect_for_sdl(
sprite_font_boundary_box(
current_position,
list_selector->font_scale,
strlen(list_selector->items[i])));
strlen(item_text)));
if (SDL_SetRenderDrawColor(camera->renderer, 255, 255, 255, 255) < 0) {
return -1;
}
@ -96,18 +59,24 @@ int list_selector_render(const Camera *camera,
}
Vec2f list_selector_size(const ListSelector *list_selector,
Vec2f font_scale,
float padding_bottom)
Vec2f font_scale,
float padding_bottom)
{
trace_assert(list_selector);
Vec2f result = vec(0.0f, 0.0f);
for (size_t i = 0; i < list_selector->count; ++i) {
for (size_t i = 0; i < list_selector->items.count; ++i) {
const char *item_text =
list_selector->list_item_text(
dynarray_pointer_at(
&list_selector->items,
i));
Rect boundary_box = sprite_font_boundary_box(
vec(0.0f, 0.0f),
font_scale,
strlen(list_selector->items[i]));
strlen(item_text));
result.x = fmaxf(result.x, boundary_box.w);
result.y += boundary_box.y + padding_bottom;
@ -116,14 +85,6 @@ Vec2f list_selector_size(const ListSelector *list_selector,
return result;
}
int list_selector_update(ListSelector *list_selector, float delta_time)
{
trace_assert(list_selector);
(void) delta_time;
return 0;
}
int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
{
trace_assert(list_selector);
@ -138,7 +99,7 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
}
break;
case SDLK_DOWN:
if (list_selector->cursor < list_selector->count - 1) {
if (list_selector->cursor < list_selector->items.count - 1) {
list_selector->cursor++;
}
break;
@ -152,11 +113,17 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
Vec2f position = list_selector->position;
for (size_t i = 0; i < list_selector->count; ++i) {
for (size_t i = 0; i < list_selector->items.count; ++i) {
const char *item_text =
list_selector->list_item_text(
dynarray_pointer_at(
&list_selector->items,
i));
Rect boundary_box = sprite_font_boundary_box(
position,
list_selector->font_scale,
strlen(list_selector->items[i]));
strlen(item_text));
if (rect_contains_point(boundary_box, mouse_pos)) {
list_selector->cursor = i;
@ -172,23 +139,27 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
// check if the click position was actually inside...
// note: make sure there's actually stuff in the list! tsoding likes
// to remove all levels and change title to "SMOL BREAK"...
if (list_selector->count == 0)
if (list_selector->items.count == 0)
break;
// note: this assumes that all list items are the same height!
// this is probably a valid assumption as long as we use a sprite font.
float single_item_height = sprite_font_boundary_box(
list_selector->position,
list_selector->font_scale,
strlen(list_selector->items[0])).h + list_selector->padding_bottom;
float single_item_height =
FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom;
Vec2f position = list_selector->position;
vec_add(&position, vec(0.0f, (float) list_selector->cursor * single_item_height));
const char *item_text =
list_selector->list_item_text(
dynarray_pointer_at(
&list_selector->items,
list_selector->cursor));
Rect boundary_box = sprite_font_boundary_box(
position,
list_selector->font_scale,
strlen(list_selector->items[list_selector->cursor]));
strlen(item_text));
const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
if (rect_contains_point(boundary_box, mouse_pos)) {
@ -201,20 +172,3 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
return 0;
}
int list_selector_selected(const ListSelector *list_selector)
{
trace_assert(list_selector);
return list_selector->selected_item;
}
void list_selector_clean_selection(ListSelector *list_selector)
{
trace_assert(list_selector);
list_selector->selected_item = -1;
}
void list_selector_move(ListSelector *list_selector, Vec2f position)
{
list_selector->position = position;
}

View File

@ -2,27 +2,32 @@
#define LIST_SELECTOR_H_
#include "game/camera.h"
#include "dynarray.h"
typedef struct ListSelector ListSelector;
typedef const char *(*ListItemText)(void *element);
ListSelector *create_list_selector(const char *items[],
size_t count,
Vec2f font_scale,
float padding_bottom);
void destroy_list_selector(ListSelector *list_selector);
typedef struct {
Dynarray items;
size_t cursor;
int selected_item;
Vec2f position;
Vec2f font_scale;
float padding_bottom;
ListItemText list_item_text;
} ListSelector;
int list_selector_render(const Camera *camera,
const ListSelector *list_selector);
Vec2f list_selector_size(const ListSelector *list_selector,
Vec2f font_scale,
float padding_bottom);
int list_selector_update(ListSelector *list_selector, float delta_time);
int list_selector_event(ListSelector *list_selector, const SDL_Event *event);
int list_selector_selected(const ListSelector *list_selector);
void list_selector_clean_selection(ListSelector *list_selector);
void list_selector_move(ListSelector *list_selector, Vec2f position);
static inline
void list_selector_clean_selection(ListSelector *list_selector)
{
trace_assert(list_selector);
list_selector->selected_item = -1;
}
#endif // LIST_SELECTOR_H_