commit
07e3416386
|
@ -37,4 +37,6 @@
|
|||
|
||||
#define TMPMEM_CAPACITY (640 * KILO)
|
||||
|
||||
#define LEVEL_EDITOR_MEMORY_CAPACITY (640 * KILO)
|
||||
|
||||
#endif // CONFIG_H_
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "system/memory.h"
|
||||
#include "system/stacktrace.h"
|
||||
|
||||
#define DYNARRAY_CAPACITY 256
|
||||
|
||||
|
@ -14,13 +16,26 @@ typedef struct {
|
|||
} Dynarray;
|
||||
|
||||
static inline
|
||||
Dynarray create_dynarray(size_t element_size)
|
||||
Dynarray create_dynarray_malloc(size_t element_size)
|
||||
{
|
||||
Dynarray result = {
|
||||
.element_size = element_size,
|
||||
.count = 0,
|
||||
.data = malloc(DYNARRAY_CAPACITY * element_size)
|
||||
};
|
||||
trace_assert(result.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
Dynarray create_dynarray(Memory *memory, size_t element_size)
|
||||
{
|
||||
trace_assert(memory);
|
||||
Dynarray result = {
|
||||
.element_size = element_size,
|
||||
.count = 0,
|
||||
.data = memory_alloc(memory, DYNARRAY_CAPACITY * element_size)
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
56
src/game.c
56
src/game.c
|
@ -24,9 +24,9 @@ typedef struct Game {
|
|||
|
||||
Game_state state;
|
||||
Sprite_font font;
|
||||
Memory tmpmem;
|
||||
Memory level_editor_memory;
|
||||
LevelPicker level_picker;
|
||||
LevelEditor level_editor;
|
||||
LevelEditor *level_editor;
|
||||
Credits credits;
|
||||
Level *level;
|
||||
Settings settings;
|
||||
|
@ -67,9 +67,9 @@ Game *create_game(const char *level_folder,
|
|||
renderer,
|
||||
"./assets/images/charmap-oldschool.bmp");
|
||||
|
||||
game->tmpmem.capacity = TMPMEM_CAPACITY;
|
||||
game->tmpmem.buffer = malloc(TMPMEM_CAPACITY);
|
||||
trace_assert(game->tmpmem.buffer);
|
||||
game->level_editor_memory.capacity = LEVEL_EDITOR_MEMORY_CAPACITY;
|
||||
game->level_editor_memory.buffer = malloc(LEVEL_EDITOR_MEMORY_CAPACITY);
|
||||
trace_assert(game->level_editor_memory.buffer);
|
||||
|
||||
level_picker_populate(&game->level_picker, level_folder);
|
||||
|
||||
|
@ -109,7 +109,9 @@ Game *create_game(const char *level_folder,
|
|||
}
|
||||
}
|
||||
|
||||
create_level_editor(&game->level_editor, &game->cursor);
|
||||
game->level_editor = create_level_editor(
|
||||
&game->level_editor_memory,
|
||||
&game->cursor);
|
||||
|
||||
game->console = PUSH_LT(
|
||||
lt,
|
||||
|
@ -129,7 +131,7 @@ void destroy_game(Game *game)
|
|||
{
|
||||
trace_assert(game);
|
||||
destroy_level_picker(game->level_picker);
|
||||
free(game->tmpmem.buffer);
|
||||
free(game->level_editor_memory.buffer);
|
||||
RETURN_LT0(game->lt);
|
||||
}
|
||||
|
||||
|
@ -151,7 +153,7 @@ int game_render(const Game *game)
|
|||
} break;
|
||||
|
||||
case GAME_STATE_LEVEL_EDITOR: {
|
||||
if (level_editor_render(&game->level_editor, &game->camera) < 0) {
|
||||
if (level_editor_render(game->level_editor, &game->camera) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} break;
|
||||
|
@ -188,7 +190,7 @@ int game_sound(Game *game)
|
|||
case GAME_STATE_LEVEL:
|
||||
return level_sound(game->level, game->sound_samples);
|
||||
case GAME_STATE_LEVEL_EDITOR:
|
||||
level_editor_sound(&game->level_editor, game->sound_samples);
|
||||
level_editor_sound(game->level_editor, game->sound_samples);
|
||||
return 0;
|
||||
case GAME_STATE_LEVEL_PICKER:
|
||||
case GAME_STATE_CREDITS:
|
||||
|
@ -248,12 +250,12 @@ int game_update(Game *game, float delta_time)
|
|||
|
||||
case GAME_STATE_LEVEL_EDITOR: {
|
||||
if (level_editor_focus_camera(
|
||||
&game->level_editor,
|
||||
game->level_editor,
|
||||
&game->camera) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
level_editor_update(&game->level_editor, delta_time);
|
||||
level_editor_update(game->level_editor, delta_time);
|
||||
} break;
|
||||
|
||||
case GAME_STATE_CREDITS: {
|
||||
|
@ -290,7 +292,7 @@ static int game_event_running(Game *game, const SDL_Event *event)
|
|||
game->lt,
|
||||
game->level,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor));
|
||||
game->level_editor));
|
||||
if (game->level == NULL) {
|
||||
game_switch_state(game, GAME_STATE_QUIT);
|
||||
return -1;
|
||||
|
@ -323,20 +325,23 @@ static int game_event_level_picker(Game *game, const SDL_Event *event)
|
|||
case SDL_KEYDOWN: {
|
||||
switch(event->key.keysym.sym) {
|
||||
case SDLK_n: {
|
||||
level_editor_clean(&game->level_editor);
|
||||
memory_clean(&game->level_editor_memory);
|
||||
game->level_editor = create_level_editor(
|
||||
&game->level_editor_memory,
|
||||
&game->cursor);
|
||||
|
||||
if (game->level == NULL) {
|
||||
game->level = PUSH_LT(
|
||||
game->lt,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor),
|
||||
game->level_editor),
|
||||
destroy_level);
|
||||
} else {
|
||||
game->level = RESET_LT(
|
||||
game->lt,
|
||||
game->level,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor));
|
||||
game->level_editor));
|
||||
}
|
||||
|
||||
if (game->level == NULL) {
|
||||
|
@ -373,7 +378,7 @@ static int game_event_level_editor(Game *game, const SDL_Event *event)
|
|||
game->lt,
|
||||
game->level,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor));
|
||||
game->level_editor));
|
||||
if (game->level == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -383,7 +388,7 @@ static int game_event_level_editor(Game *game, const SDL_Event *event)
|
|||
} break;
|
||||
}
|
||||
|
||||
return level_editor_event(&game->level_editor, event, &game->camera);
|
||||
return level_editor_event(game->level_editor, event, &game->camera, &game->level_editor_memory);
|
||||
}
|
||||
|
||||
int game_event(Game *game, const SDL_Event *event)
|
||||
|
@ -526,21 +531,30 @@ int game_load_level(Game *game, const char *level_filename)
|
|||
trace_assert(game);
|
||||
trace_assert(level_filename);
|
||||
|
||||
memory_clean(&game->tmpmem);
|
||||
level_editor_load_from_file(&game->level_editor, &game->tmpmem, level_filename);
|
||||
memory_clean(&game->level_editor_memory);
|
||||
game->level_editor =
|
||||
create_level_editor_from_file(
|
||||
&game->level_editor_memory,
|
||||
&game->cursor,
|
||||
level_filename);
|
||||
|
||||
if (!game->level_editor) {
|
||||
game_switch_state(game, GAME_STATE_LEVEL_PICKER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (game->level == NULL) {
|
||||
game->level = PUSH_LT(
|
||||
game->lt,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor),
|
||||
game->level_editor),
|
||||
destroy_level);
|
||||
} else {
|
||||
game->level = RESET_LT(
|
||||
game->lt,
|
||||
game->level,
|
||||
create_level_from_level_editor(
|
||||
&game->level_editor));
|
||||
game->level_editor));
|
||||
}
|
||||
|
||||
if (game->level == NULL) {
|
||||
|
|
|
@ -86,7 +86,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->platforms = PUSH_LT(
|
||||
lt,
|
||||
create_platforms_from_rect_layer(&level_editor->platforms_layer),
|
||||
create_platforms_from_rect_layer(level_editor->platforms_layer),
|
||||
destroy_platforms);
|
||||
if (level->platforms == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -94,7 +94,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->goals = PUSH_LT(
|
||||
lt,
|
||||
create_goals_from_point_layer(&level_editor->goals_layer),
|
||||
create_goals_from_point_layer(level_editor->goals_layer),
|
||||
destroy_goals);
|
||||
if (level->goals == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -102,7 +102,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->lava = PUSH_LT(
|
||||
lt,
|
||||
create_lava_from_rect_layer(&level_editor->lava_layer),
|
||||
create_lava_from_rect_layer(level_editor->lava_layer),
|
||||
destroy_lava);
|
||||
if (level->lava == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -110,7 +110,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->back_platforms = PUSH_LT(
|
||||
lt,
|
||||
create_platforms_from_rect_layer(&level_editor->back_platforms_layer),
|
||||
create_platforms_from_rect_layer(level_editor->back_platforms_layer),
|
||||
destroy_platforms);
|
||||
if (level->back_platforms == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -118,7 +118,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->boxes = PUSH_LT(
|
||||
lt,
|
||||
create_boxes_from_rect_layer(&level_editor->boxes_layer, level->rigid_bodies),
|
||||
create_boxes_from_rect_layer(level_editor->boxes_layer, level->rigid_bodies),
|
||||
destroy_boxes);
|
||||
if (level->boxes == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -126,7 +126,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
|
||||
level->labels = PUSH_LT(
|
||||
lt,
|
||||
create_labels_from_label_layer(&level_editor->label_layer),
|
||||
create_labels_from_label_layer(level_editor->label_layer),
|
||||
destroy_labels);
|
||||
if (level->labels == NULL) {
|
||||
RETURN_LT(lt, NULL);
|
||||
|
@ -135,7 +135,7 @@ Level *create_level_from_level_editor(const LevelEditor *level_editor)
|
|||
level->regions = PUSH_LT(
|
||||
lt,
|
||||
create_regions_from_rect_layer(
|
||||
&level_editor->regions_layer,
|
||||
level_editor->regions_layer,
|
||||
level->labels,
|
||||
level->goals),
|
||||
destroy_regions);
|
||||
|
|
|
@ -34,9 +34,9 @@ Boxes *create_boxes_from_rect_layer(const RectLayer *layer, RigidBodies *rigid_b
|
|||
}
|
||||
boxes->lt = lt;
|
||||
|
||||
boxes->boxes_ids = create_dynarray(ENTITY_MAX_ID_SIZE);
|
||||
boxes->body_ids = create_dynarray(sizeof(RigidBodyId));
|
||||
boxes->body_colors = create_dynarray(sizeof(Color));
|
||||
boxes->boxes_ids = create_dynarray_malloc(ENTITY_MAX_ID_SIZE);
|
||||
boxes->body_ids = create_dynarray_malloc(sizeof(RigidBodyId));
|
||||
boxes->body_colors = create_dynarray_malloc(sizeof(Color));
|
||||
|
||||
boxes->rigid_bodies = rigid_bodies;
|
||||
|
||||
|
|
|
@ -32,8 +32,9 @@ static int level_editor_dump(LevelEditor *level_editor);
|
|||
|
||||
// TODO(#994): too much duplicate code between create_level_editor and create_level_editor_from_file
|
||||
|
||||
void create_level_editor(LevelEditor *level_editor, Cursor *cursor)
|
||||
LevelEditor *create_level_editor(Memory *memory, Cursor *cursor)
|
||||
{
|
||||
LevelEditor *level_editor = memory_alloc(memory, sizeof(LevelEditor));
|
||||
memset(level_editor, 0, sizeof(*level_editor));
|
||||
|
||||
level_editor->edit_field_filename.font_size = LEVEL_EDITOR_EDIT_FIELD_SIZE;
|
||||
|
@ -41,23 +42,25 @@ void create_level_editor(LevelEditor *level_editor, Cursor *cursor)
|
|||
|
||||
level_editor->background_layer = create_background_layer(hexstr("fffda5"));
|
||||
level_editor->player_layer = create_player_layer(vec(0.0f, 0.0f), hexstr("ff8080"));
|
||||
level_editor->platforms_layer = create_rect_layer("platform", cursor);
|
||||
level_editor->goals_layer = create_point_layer("goal"),
|
||||
level_editor->lava_layer = create_rect_layer("lava", cursor);
|
||||
level_editor->back_platforms_layer = create_rect_layer("back_platform", cursor);
|
||||
level_editor->boxes_layer = create_rect_layer("box", cursor);
|
||||
level_editor->label_layer = create_label_layer("label");
|
||||
level_editor->regions_layer = create_rect_layer("region", cursor),
|
||||
|
||||
level_editor->layers[LAYER_PICKER_BOXES] = rect_layer_as_layer(&level_editor->boxes_layer);
|
||||
level_editor->layers[LAYER_PICKER_PLATFORMS] = rect_layer_as_layer(&level_editor->platforms_layer);
|
||||
level_editor->layers[LAYER_PICKER_BACK_PLATFORMS] = rect_layer_as_layer(&level_editor->back_platforms_layer);
|
||||
level_editor->layers[LAYER_PICKER_GOALS] = point_layer_as_layer(&level_editor->goals_layer);
|
||||
level_editor->platforms_layer = create_rect_layer(memory, "platform", cursor);
|
||||
level_editor->lava_layer = create_rect_layer(memory, "lava", cursor);
|
||||
level_editor->back_platforms_layer = create_rect_layer(memory, "back_platform", cursor);
|
||||
level_editor->boxes_layer = create_rect_layer(memory, "box", cursor);
|
||||
level_editor->regions_layer = create_rect_layer(memory, "region", cursor);
|
||||
level_editor->goals_layer = create_point_layer(memory, "goal");
|
||||
level_editor->label_layer = create_label_layer(memory, "label");
|
||||
|
||||
level_editor->layers[LAYER_PICKER_BOXES] = rect_layer_as_layer(level_editor->boxes_layer);
|
||||
level_editor->layers[LAYER_PICKER_PLATFORMS] = rect_layer_as_layer(level_editor->platforms_layer);
|
||||
level_editor->layers[LAYER_PICKER_BACK_PLATFORMS] = rect_layer_as_layer(level_editor->back_platforms_layer);
|
||||
level_editor->layers[LAYER_PICKER_GOALS] = point_layer_as_layer(level_editor->goals_layer);
|
||||
level_editor->layers[LAYER_PICKER_PLAYER] = player_layer_as_layer(&level_editor->player_layer);
|
||||
level_editor->layers[LAYER_PICKER_LAVA] = rect_layer_as_layer(&level_editor->lava_layer);
|
||||
level_editor->layers[LAYER_PICKER_REGIONS] = rect_layer_as_layer(&level_editor->regions_layer);
|
||||
level_editor->layers[LAYER_PICKER_LAVA] = rect_layer_as_layer(level_editor->lava_layer);
|
||||
level_editor->layers[LAYER_PICKER_REGIONS] = rect_layer_as_layer(level_editor->regions_layer);
|
||||
level_editor->layers[LAYER_PICKER_BACKGROUND] = background_layer_as_layer(&level_editor->background_layer);
|
||||
level_editor->layers[LAYER_PICKER_LABELS] = label_layer_as_layer(&level_editor->label_layer);
|
||||
level_editor->layers[LAYER_PICKER_LABELS] = label_layer_as_layer(level_editor->label_layer);
|
||||
|
||||
|
||||
level_editor->notice = (FadingWigglyText) {
|
||||
.wiggly_text = {
|
||||
|
@ -69,17 +72,21 @@ void create_level_editor(LevelEditor *level_editor, Cursor *cursor)
|
|||
};
|
||||
|
||||
level_editor->camera_scale = 1.0f;
|
||||
level_editor->undo_history = create_undo_history();
|
||||
level_editor->undo_history = create_undo_history(memory);
|
||||
|
||||
return level_editor;
|
||||
}
|
||||
|
||||
void level_editor_load_from_file(LevelEditor *level_editor, Memory *tmpmem, const char *file_name)
|
||||
LevelEditor *create_level_editor_from_file(Memory *memory, Cursor *cursor, const char *file_name)
|
||||
{
|
||||
trace_assert(memory);
|
||||
trace_assert(cursor);
|
||||
trace_assert(file_name);
|
||||
|
||||
if (level_editor->file_name) free(level_editor->file_name);
|
||||
level_editor->file_name = string_duplicate(file_name, NULL);
|
||||
LevelEditor *level_editor = create_level_editor(memory, cursor);
|
||||
level_editor->file_name = strdup_to_memory(memory, file_name);
|
||||
|
||||
String input = read_whole_file(tmpmem, file_name);
|
||||
String input = read_whole_file(memory, file_name);
|
||||
trace_assert(input.data);
|
||||
|
||||
String version = trim(chop_by_delim(&input, '\n'));
|
||||
|
@ -90,58 +97,23 @@ void level_editor_load_from_file(LevelEditor *level_editor, Memory *tmpmem, cons
|
|||
// Nothing
|
||||
} else {
|
||||
log_fail("Version `%s` is not supported. Expected version `%s`.\n",
|
||||
string_to_cstr(tmpmem, version),
|
||||
string_to_cstr(memory, version),
|
||||
VERSION);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
level_editor->background_layer = chop_background_layer(&input);
|
||||
level_editor->player_layer = chop_player_layer(tmpmem, &input);
|
||||
rect_layer_reload(&level_editor->platforms_layer, tmpmem, &input);
|
||||
point_layer_reload(&level_editor->goals_layer, tmpmem, &input);
|
||||
rect_layer_reload(&level_editor->lava_layer, tmpmem, &input);
|
||||
rect_layer_reload(&level_editor->back_platforms_layer, tmpmem, &input);
|
||||
rect_layer_reload(&level_editor->boxes_layer, tmpmem, &input);
|
||||
label_layer_reload(&level_editor->label_layer, tmpmem, &input);
|
||||
rect_layer_reload(&level_editor->regions_layer, tmpmem, &input);
|
||||
undo_history_clean(&level_editor->undo_history);
|
||||
}
|
||||
level_editor->player_layer = chop_player_layer(memory, &input);
|
||||
rect_layer_load(level_editor->platforms_layer, memory, &input);
|
||||
point_layer_load(level_editor->goals_layer, memory, &input);
|
||||
rect_layer_load(level_editor->lava_layer, memory, &input);
|
||||
rect_layer_load(level_editor->back_platforms_layer, memory, &input);
|
||||
rect_layer_load(level_editor->boxes_layer, memory, &input);
|
||||
label_layer_load(level_editor->label_layer, memory, &input);
|
||||
rect_layer_load(level_editor->regions_layer, memory, &input);
|
||||
undo_history_clean(level_editor->undo_history);
|
||||
|
||||
void level_editor_clean(LevelEditor *level_editor)
|
||||
{
|
||||
level_editor->camera_scale = 1.0f;
|
||||
level_editor->camera_position = vec(0.0f, 0.0f);
|
||||
if (level_editor->file_name) {
|
||||
free(level_editor->file_name);
|
||||
level_editor->file_name = NULL;
|
||||
}
|
||||
level_editor->background_layer = create_background_layer(hexstr("fffda5"));
|
||||
level_editor->player_layer = create_player_layer(vec(0.0f, 0.0f), hexstr("ff8080"));
|
||||
rect_layer_clean(&level_editor->platforms_layer);
|
||||
point_layer_clean(&level_editor->goals_layer);
|
||||
rect_layer_clean(&level_editor->lava_layer);
|
||||
rect_layer_clean(&level_editor->back_platforms_layer);
|
||||
rect_layer_clean(&level_editor->boxes_layer);
|
||||
label_layer_clean(&level_editor->label_layer);
|
||||
rect_layer_clean(&level_editor->regions_layer);
|
||||
undo_history_clean(&level_editor->undo_history);
|
||||
}
|
||||
|
||||
void destroy_level_editor(LevelEditor *level_editor)
|
||||
{
|
||||
trace_assert(level_editor);
|
||||
destroy_undo_history(level_editor->undo_history);
|
||||
destroy_rect_layer(level_editor->boxes_layer);
|
||||
destroy_rect_layer(level_editor->platforms_layer);
|
||||
destroy_rect_layer(level_editor->back_platforms_layer);
|
||||
destroy_point_layer(level_editor->goals_layer);
|
||||
destroy_rect_layer(level_editor->lava_layer);
|
||||
destroy_rect_layer(level_editor->regions_layer);
|
||||
destroy_label_layer(level_editor->label_layer);
|
||||
|
||||
if (level_editor->file_name) {
|
||||
free(level_editor->file_name);
|
||||
}
|
||||
return level_editor;
|
||||
}
|
||||
|
||||
int level_editor_render(const LevelEditor *level_editor,
|
||||
|
@ -218,7 +190,8 @@ int level_editor_render(const LevelEditor *level_editor,
|
|||
static
|
||||
int level_editor_saveas_event(LevelEditor *level_editor,
|
||||
const SDL_Event *event,
|
||||
const Camera *camera)
|
||||
const Camera *camera,
|
||||
Memory *memory)
|
||||
{
|
||||
trace_assert(level_editor);
|
||||
trace_assert(event);
|
||||
|
@ -234,7 +207,7 @@ int level_editor_saveas_event(LevelEditor *level_editor,
|
|||
LEVEL_FOLDER_MAX_LENGTH,
|
||||
"./assets/levels/%s.txt",
|
||||
edit_field_as_text(&level_editor->edit_field_filename));
|
||||
level_editor->file_name = string_duplicate(path, NULL);
|
||||
level_editor->file_name = strdup_to_memory(memory, path);
|
||||
level_editor_dump(level_editor);
|
||||
SDL_StopTextInput();
|
||||
level_editor->state = LEVEL_EDITOR_IDLE;
|
||||
|
@ -272,10 +245,10 @@ int level_editor_idle_event(LevelEditor *level_editor,
|
|||
|
||||
case SDLK_z: {
|
||||
if (event->key.keysym.mod & KMOD_CTRL) {
|
||||
if (undo_history_empty(&level_editor->undo_history)) {
|
||||
if (undo_history_empty(level_editor->undo_history)) {
|
||||
level_editor->bell = 1;
|
||||
}
|
||||
undo_history_pop(&level_editor->undo_history);
|
||||
undo_history_pop(level_editor->undo_history);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -342,7 +315,7 @@ int level_editor_idle_event(LevelEditor *level_editor,
|
|||
level_editor->layers[level_editor->layer_picker],
|
||||
event,
|
||||
camera,
|
||||
&level_editor->undo_history) < 0) {
|
||||
level_editor->undo_history) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
@ -355,7 +328,8 @@ int level_editor_idle_event(LevelEditor *level_editor,
|
|||
|
||||
int level_editor_event(LevelEditor *level_editor,
|
||||
const SDL_Event *event,
|
||||
Camera *camera)
|
||||
Camera *camera,
|
||||
Memory *memory)
|
||||
{
|
||||
trace_assert(level_editor);
|
||||
trace_assert(event);
|
||||
|
@ -366,7 +340,7 @@ int level_editor_event(LevelEditor *level_editor,
|
|||
return level_editor_idle_event(level_editor, event, camera);
|
||||
|
||||
case LEVEL_EDITOR_SAVEAS:
|
||||
return level_editor_saveas_event(level_editor, event, camera);
|
||||
return level_editor_saveas_event(level_editor, event, camera, memory);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -27,19 +27,19 @@ struct LevelEditor
|
|||
LayerPicker layer_picker;
|
||||
FadingWigglyText notice;
|
||||
|
||||
RectLayer boxes_layer;
|
||||
RectLayer platforms_layer;
|
||||
RectLayer back_platforms_layer;
|
||||
PointLayer goals_layer;
|
||||
RectLayer *boxes_layer;
|
||||
RectLayer *platforms_layer;
|
||||
RectLayer *back_platforms_layer;
|
||||
PointLayer *goals_layer;
|
||||
PlayerLayer player_layer;
|
||||
RectLayer lava_layer;
|
||||
RectLayer regions_layer;
|
||||
RectLayer *lava_layer;
|
||||
RectLayer *regions_layer;
|
||||
BackgroundLayer background_layer;
|
||||
LabelLayer label_layer;
|
||||
LabelLayer *label_layer;
|
||||
|
||||
LayerPtr layers[LAYER_PICKER_N];
|
||||
|
||||
UndoHistory undo_history;
|
||||
UndoHistory *undo_history;
|
||||
|
||||
bool drag;
|
||||
int bell;
|
||||
|
@ -49,16 +49,15 @@ struct LevelEditor
|
|||
char *file_name;
|
||||
};
|
||||
|
||||
void create_level_editor(LevelEditor *level_editor, Cursor *cursor);
|
||||
void level_editor_load_from_file(LevelEditor *level_editor, Memory *tmpmem, const char *file_name);
|
||||
void level_editor_clean(LevelEditor *level_editor);
|
||||
void destroy_level_editor(LevelEditor *level_editor);
|
||||
LevelEditor *create_level_editor(Memory *memory, Cursor *cursor);
|
||||
LevelEditor *create_level_editor_from_file(Memory *memory, Cursor *cursor, const char *file_name);
|
||||
|
||||
int level_editor_render(const LevelEditor *level_editor,
|
||||
const Camera *camera);
|
||||
int level_editor_event(LevelEditor *level_editor,
|
||||
const SDL_Event *event,
|
||||
Camera *camera);
|
||||
Camera *camera,
|
||||
Memory *memory);
|
||||
int level_editor_focus_camera(LevelEditor *level_editor,
|
||||
Camera *camera);
|
||||
int level_editor_update(LevelEditor *level_editor, float delta_time);
|
||||
|
|
|
@ -141,22 +141,27 @@ LayerPtr label_layer_as_layer(LabelLayer *label_layer)
|
|||
return layer;
|
||||
}
|
||||
|
||||
LabelLayer create_label_layer(const char *id_name_prefix)
|
||||
LabelLayer *create_label_layer(Memory *memory,
|
||||
const char *id_name_prefix)
|
||||
{
|
||||
LabelLayer result = {0};
|
||||
result.ids = create_dynarray(sizeof(char) * LABEL_LAYER_ID_MAX_SIZE);
|
||||
result.positions = create_dynarray(sizeof(Vec2f));
|
||||
result.colors = create_dynarray(sizeof(Color));
|
||||
result.texts = create_dynarray(sizeof(char) * LABEL_LAYER_TEXT_MAX_SIZE);
|
||||
result.color_picker = create_color_picker_from_rgba(COLOR_RED);
|
||||
result.selection = -1;
|
||||
result.edit_field.font_size = LABELS_SIZE;
|
||||
result.edit_field.font_color = COLOR_RED;
|
||||
result.id_name_prefix = id_name_prefix;
|
||||
trace_assert(memory);
|
||||
trace_assert(id_name_prefix);
|
||||
|
||||
LabelLayer *result = memory_alloc(memory, sizeof(LabelLayer));
|
||||
memset(result, 0, sizeof(LabelLayer));
|
||||
result->ids = create_dynarray(memory, sizeof(char) * LABEL_LAYER_ID_MAX_SIZE);
|
||||
result->positions = create_dynarray(memory, sizeof(Vec2f));
|
||||
result->colors = create_dynarray(memory, sizeof(Color));
|
||||
result->texts = create_dynarray(memory, sizeof(char) * LABEL_LAYER_TEXT_MAX_SIZE);
|
||||
result->color_picker = create_color_picker_from_rgba(COLOR_RED);
|
||||
result->selection = -1;
|
||||
result->edit_field.font_size = LABELS_SIZE;
|
||||
result->edit_field.font_color = COLOR_RED;
|
||||
result->id_name_prefix = id_name_prefix;
|
||||
return result;
|
||||
}
|
||||
|
||||
void label_layer_reload(LabelLayer *label_layer,
|
||||
void label_layer_load(LabelLayer *label_layer,
|
||||
Memory *memory,
|
||||
String *input)
|
||||
{
|
||||
|
@ -164,8 +169,6 @@ void label_layer_reload(LabelLayer *label_layer,
|
|||
trace_assert(memory);
|
||||
trace_assert(input);
|
||||
|
||||
label_layer_clean(label_layer);
|
||||
|
||||
int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
|
||||
char id[LABEL_LAYER_ID_MAX_SIZE];
|
||||
char label_text[LABEL_LAYER_TEXT_MAX_SIZE];
|
||||
|
@ -200,15 +203,6 @@ void label_layer_reload(LabelLayer *label_layer,
|
|||
}
|
||||
}
|
||||
|
||||
void label_layer_clean(LabelLayer *label_layer)
|
||||
{
|
||||
trace_assert(label_layer);
|
||||
dynarray_clear(&label_layer->ids);
|
||||
dynarray_clear(&label_layer->positions);
|
||||
dynarray_clear(&label_layer->colors);
|
||||
dynarray_clear(&label_layer->texts);
|
||||
}
|
||||
|
||||
static inline
|
||||
Rect boundary_of_element(const LabelLayer *label_layer,
|
||||
size_t i,
|
||||
|
|
|
@ -40,11 +40,10 @@ LayerPtr label_layer_as_layer(LabelLayer *label_layer);
|
|||
|
||||
// NOTE: create_label_layer and create_label_layer_from_line_stream do
|
||||
// not own id_name_prefix
|
||||
LabelLayer create_label_layer(const char *id_name_prefix);
|
||||
void label_layer_reload(LabelLayer *label_layer,
|
||||
LabelLayer *create_label_layer(Memory *memory, const char *id_name_prefix);
|
||||
void label_layer_load(LabelLayer *label_layer,
|
||||
Memory *memory,
|
||||
String *input);
|
||||
void label_layer_clean(LabelLayer *label_layer);
|
||||
|
||||
static inline
|
||||
void destroy_label_layer(LabelLayer label_layer)
|
||||
|
|
|
@ -139,29 +139,32 @@ LayerPtr point_layer_as_layer(PointLayer *point_layer)
|
|||
return layer;
|
||||
}
|
||||
|
||||
PointLayer create_point_layer(const char *id_name_prefix)
|
||||
PointLayer *create_point_layer(Memory *memory,
|
||||
const char *id_name_prefix)
|
||||
{
|
||||
PointLayer result = {0};
|
||||
result.state = POINT_LAYER_IDLE;
|
||||
result.positions = create_dynarray(sizeof(Vec2f));
|
||||
result.colors = create_dynarray(sizeof(Color));
|
||||
result.ids = create_dynarray(sizeof(char) * ID_MAX_SIZE);
|
||||
result.edit_field.font_size = POINT_LAYER_ID_TEXT_SIZE;
|
||||
result.edit_field.font_color = POINT_LAYER_ID_TEXT_COLOR;
|
||||
result.id_name_prefix = id_name_prefix;
|
||||
trace_assert(memory);
|
||||
trace_assert(id_name_prefix);
|
||||
|
||||
PointLayer *result = memory_alloc(memory, sizeof(PointLayer));
|
||||
memset(result, 0, sizeof(PointLayer));
|
||||
result->state = POINT_LAYER_IDLE;
|
||||
result->positions = create_dynarray(memory, sizeof(Vec2f));
|
||||
result->colors = create_dynarray(memory, sizeof(Color));
|
||||
result->ids = create_dynarray(memory, sizeof(char) * ID_MAX_SIZE);
|
||||
result->edit_field.font_size = POINT_LAYER_ID_TEXT_SIZE;
|
||||
result->edit_field.font_color = POINT_LAYER_ID_TEXT_COLOR;
|
||||
result->id_name_prefix = id_name_prefix;
|
||||
return result;
|
||||
}
|
||||
|
||||
void point_layer_reload(PointLayer *point_layer,
|
||||
Memory *memory,
|
||||
String *input)
|
||||
void point_layer_load(PointLayer *point_layer,
|
||||
Memory *memory,
|
||||
String *input)
|
||||
{
|
||||
trace_assert(point_layer);
|
||||
trace_assert(memory);
|
||||
trace_assert(input);
|
||||
|
||||
point_layer_clean(point_layer);
|
||||
|
||||
int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
|
||||
char id[ENTITY_MAX_ID_SIZE];
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
@ -181,14 +184,6 @@ void point_layer_reload(PointLayer *point_layer,
|
|||
}
|
||||
}
|
||||
|
||||
void point_layer_clean(PointLayer *point_layer)
|
||||
{
|
||||
trace_assert(point_layer);
|
||||
dynarray_clear(&point_layer->positions);
|
||||
dynarray_clear(&point_layer->colors);
|
||||
dynarray_clear(&point_layer->ids);
|
||||
}
|
||||
|
||||
static inline
|
||||
Triangle element_shape(Vec2f position, float scale)
|
||||
{
|
||||
|
|
|
@ -37,12 +37,10 @@ typedef struct {
|
|||
LayerPtr point_layer_as_layer(PointLayer *point_layer);
|
||||
// NOTE: create_point_layer and create_point_layer_from_line_stream do
|
||||
// not own id_name_prefix
|
||||
PointLayer create_point_layer(const char *id_name_prefix);
|
||||
void point_layer_reload(PointLayer *point_layer,
|
||||
PointLayer *create_point_layer(Memory *memory, const char *id_name_prefix);
|
||||
void point_layer_load(PointLayer *point_layer,
|
||||
Memory *memory,
|
||||
String *input);
|
||||
void point_layer_clean(PointLayer *point_layer);
|
||||
|
||||
|
||||
static inline
|
||||
void destroy_point_layer(PointLayer point_layer)
|
||||
|
|
|
@ -796,34 +796,36 @@ LayerPtr rect_layer_as_layer(RectLayer *rect_layer)
|
|||
return layer;
|
||||
}
|
||||
|
||||
RectLayer create_rect_layer(const char *id_name_prefix, Cursor *cursor)
|
||||
RectLayer *create_rect_layer(Memory *memory,
|
||||
const char *id_name_prefix,
|
||||
Cursor *cursor)
|
||||
{
|
||||
trace_assert(memory);
|
||||
trace_assert(id_name_prefix);
|
||||
trace_assert(cursor);
|
||||
|
||||
RectLayer result = {0};
|
||||
RectLayer *rect_layer = memory_alloc(memory, sizeof(RectLayer));
|
||||
|
||||
result.ids = create_dynarray(sizeof(char) * ENTITY_MAX_ID_SIZE);
|
||||
result.rects = create_dynarray(sizeof(Rect));
|
||||
result.colors = create_dynarray(sizeof(Color));
|
||||
result.actions = create_dynarray(sizeof(Action));
|
||||
result.id_edit_field.font_size = RECT_LAYER_ID_LABEL_SIZE;
|
||||
result.id_edit_field.font_color = COLOR_BLACK;
|
||||
result.color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
result.selection = -1;
|
||||
result.id_name_prefix = id_name_prefix;
|
||||
result.cursor = cursor;
|
||||
rect_layer->ids = create_dynarray(memory, sizeof(char) * ENTITY_MAX_ID_SIZE);
|
||||
rect_layer->rects = create_dynarray(memory, sizeof(Rect));
|
||||
rect_layer->colors = create_dynarray(memory, sizeof(Color));
|
||||
rect_layer->actions = create_dynarray(memory, sizeof(Action));
|
||||
rect_layer->id_edit_field.font_size = RECT_LAYER_ID_LABEL_SIZE;
|
||||
rect_layer->id_edit_field.font_color = COLOR_BLACK;
|
||||
rect_layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
rect_layer->selection = -1;
|
||||
rect_layer->id_name_prefix = id_name_prefix;
|
||||
rect_layer->cursor = cursor;
|
||||
|
||||
return result;
|
||||
return rect_layer;
|
||||
}
|
||||
|
||||
void rect_layer_reload(RectLayer *layer, Memory *memory, String *input)
|
||||
void rect_layer_load(RectLayer *layer, Memory *memory, String *input)
|
||||
{
|
||||
trace_assert(layer);
|
||||
trace_assert(memory);
|
||||
trace_assert(input);
|
||||
|
||||
rect_layer_clean(layer);
|
||||
|
||||
int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
|
||||
char id[ENTITY_MAX_ID_SIZE];
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
@ -876,15 +878,6 @@ void rect_layer_reload(RectLayer *layer, Memory *memory, String *input)
|
|||
}
|
||||
}
|
||||
|
||||
void rect_layer_clean(RectLayer *rect_layer)
|
||||
{
|
||||
trace_assert(rect_layer);
|
||||
dynarray_clear(&rect_layer->ids);
|
||||
dynarray_clear(&rect_layer->rects);
|
||||
dynarray_clear(&rect_layer->colors);
|
||||
dynarray_clear(&rect_layer->actions);
|
||||
}
|
||||
|
||||
int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
|
||||
{
|
||||
trace_assert(layer);
|
||||
|
|
|
@ -45,10 +45,11 @@ struct RectLayer {
|
|||
LayerPtr rect_layer_as_layer(RectLayer *layer);
|
||||
// NOTE: create_rect_layer and create_rect_layer_from_line_stream does
|
||||
// not own id_name_prefix
|
||||
RectLayer create_rect_layer(const char *id_name_prefix,
|
||||
Cursor *cursor);
|
||||
void rect_layer_reload(RectLayer *rect_layer, Memory *memory, String *input);
|
||||
void rect_layer_clean(RectLayer *rect_layer);
|
||||
|
||||
RectLayer *create_rect_layer(Memory *memory,
|
||||
const char *id_name_prefix,
|
||||
Cursor *cursor);
|
||||
void rect_layer_load(RectLayer *rect_layer, Memory *memory, String *input);
|
||||
|
||||
static inline
|
||||
void destroy_rect_layer(RectLayer layer)
|
||||
|
|
|
@ -14,19 +14,14 @@ typedef struct {
|
|||
size_t context_data_size;
|
||||
} HistoryItem;
|
||||
|
||||
static
|
||||
void undo_history_destroy_item(void *item)
|
||||
UndoHistory *create_undo_history(Memory *memory)
|
||||
{
|
||||
free(((HistoryItem*)item)->context_data);
|
||||
}
|
||||
|
||||
UndoHistory create_undo_history(void)
|
||||
{
|
||||
UndoHistory result;
|
||||
result.actions = create_ring_buffer(
|
||||
UndoHistory *result = memory_alloc(memory, sizeof(UndoHistory));
|
||||
result->actions = create_ring_buffer_from_buffer(
|
||||
memory,
|
||||
sizeof(HistoryItem),
|
||||
UNDO_HISTORY_CAPACITY,
|
||||
undo_history_destroy_item);
|
||||
UNDO_HISTORY_CAPACITY);
|
||||
result->memory = memory;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -37,14 +32,13 @@ void undo_history_push(UndoHistory *undo_history,
|
|||
{
|
||||
trace_assert(undo_history);
|
||||
|
||||
// TODO: undo_history_push kinda leaks the memory
|
||||
HistoryItem item = {
|
||||
.revert = revert,
|
||||
.context_data = malloc(context_data_size),
|
||||
.context_data = memory_alloc(undo_history->memory, context_data_size),
|
||||
.context_data_size = context_data_size
|
||||
};
|
||||
trace_assert(item.context_data);
|
||||
memcpy(item.context_data, context_data, context_data_size);
|
||||
|
||||
ring_buffer_push(&undo_history->actions, &item);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,15 +7,10 @@ typedef void (*RevertAction)(void *context, size_t context_size);
|
|||
|
||||
typedef struct {
|
||||
RingBuffer actions;
|
||||
Memory *memory;
|
||||
} UndoHistory;
|
||||
|
||||
UndoHistory create_undo_history(void);
|
||||
|
||||
static inline
|
||||
void destroy_undo_history(UndoHistory undo_history)
|
||||
{
|
||||
destroy_ring_buffer(undo_history.actions);
|
||||
}
|
||||
UndoHistory *create_undo_history(Memory *memory);
|
||||
|
||||
void undo_history_push(UndoHistory *undo_history,
|
||||
RevertAction revert,
|
||||
|
|
|
@ -32,7 +32,7 @@ void level_picker_populate(LevelPicker *level_picker,
|
|||
|
||||
{
|
||||
dynarray_clear(&level_picker->items);
|
||||
level_picker->items = create_dynarray(METADATA_FILEPATH_MAX_SIZE);
|
||||
level_picker->items = create_dynarray_malloc(METADATA_FILEPATH_MAX_SIZE);
|
||||
|
||||
DIR *level_dir = opendir(dirpath);
|
||||
if (level_dir == NULL) {
|
||||
|
|
|
@ -16,7 +16,6 @@ void ring_buffer_push(RingBuffer *buffer,
|
|||
buffer->element_size);
|
||||
buffer->count += 1;
|
||||
} else {
|
||||
if (buffer->dtor) buffer->dtor(buffer->data + i * buffer->element_size);
|
||||
memcpy(
|
||||
buffer->data + i * buffer->element_size,
|
||||
element,
|
||||
|
@ -30,12 +29,6 @@ int ring_buffer_pop(RingBuffer *buffer)
|
|||
trace_assert(buffer);
|
||||
|
||||
if (buffer->count == 0) return 0;
|
||||
|
||||
if (buffer->dtor) {
|
||||
size_t i = (buffer->begin + buffer->count - 1) % buffer->capacity;
|
||||
buffer->dtor(buffer->data + i * buffer->element_size);
|
||||
}
|
||||
|
||||
buffer->count--;
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "system/memory.h"
|
||||
|
||||
typedef void (*RingBufferDtor)(void *element);
|
||||
|
||||
typedef struct {
|
||||
|
@ -15,28 +17,20 @@ typedef struct {
|
|||
size_t count;
|
||||
size_t begin;
|
||||
uint8_t *data;
|
||||
RingBufferDtor dtor;
|
||||
} RingBuffer;
|
||||
|
||||
static inline
|
||||
RingBuffer create_ring_buffer(size_t element_size,
|
||||
size_t capacity,
|
||||
RingBufferDtor dtor)
|
||||
RingBuffer create_ring_buffer_from_buffer(Memory *memory,
|
||||
size_t element_size,
|
||||
size_t capacity)
|
||||
{
|
||||
RingBuffer result = {0};
|
||||
result.element_size = element_size;
|
||||
result.capacity = capacity;
|
||||
result.dtor = dtor;
|
||||
result.data = malloc(result.element_size * result.capacity);
|
||||
result.data = memory_alloc(memory, result.element_size * result.capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
void destroy_ring_buffer(RingBuffer buffer)
|
||||
{
|
||||
free(buffer.data);
|
||||
}
|
||||
|
||||
void ring_buffer_push(RingBuffer *buffer, void *element);
|
||||
int ring_buffer_pop(RingBuffer *buffer);
|
||||
void *ring_buffer_top(RingBuffer *buffer);
|
||||
|
|
|
@ -20,7 +20,6 @@ void *memory_alloc(Memory *memory, size_t size)
|
|||
assert(memory);
|
||||
assert(memory->size + size <= memory->capacity);
|
||||
|
||||
|
||||
void *result = memory->buffer + memory->size;
|
||||
memory->size += size;
|
||||
|
||||
|
|
|
@ -120,4 +120,16 @@ char *string_to_cstr(Memory *memory, String s)
|
|||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
char *strdup_to_memory(Memory *memory, const char *s)
|
||||
{
|
||||
trace_assert(memory);
|
||||
trace_assert(s);
|
||||
|
||||
const size_t n = strlen(s) + 1;
|
||||
char *d = memory_alloc(memory, n);
|
||||
memcpy(d, s, n);
|
||||
return d;
|
||||
}
|
||||
|
||||
#endif // S_H_
|
||||
|
|
Loading…
Reference in New Issue