#include "game/camera.h"
#include "game/sound_samples.h"
-#include "game/level_metadata.h"
#include "game/level/boxes.h"
-#include "game/level/level_editor/action_picker.h"
#include "game/level/level_editor/color_picker.h"
#include "game/level/level_editor/rect_layer.h"
#include "game/level/level_editor/point_layer.h"
#include "ui/edit_field.h"
#include "system/stacktrace.h"
#include "system/nth_alloc.h"
-#include "system/lt.h"
-#include "system/lt_adapters.h"
#include "system/log.h"
#include "system/str.h"
#include "config.h"
#include "math/extrema.h"
+#include "system/file.h"
#include "level_editor.h"
-#define DEFAULT_LEVEL_TITLE "New Level"
-
#define LEVEL_FOLDER_MAX_LENGTH 512
-#define LEVEL_LINE_MAX_LENGTH 512
#define LEVEL_EDITOR_EDIT_FIELD_SIZE vec(5.0f, 5.0f)
#define LEVEL_EDITOR_EDIT_FIELD_COLOR COLOR_BLACK
// TODO(#994): too much duplicate code between create_level_editor and create_level_editor_from_file
-LevelEditor *create_level_editor(Cursor *cursor)
+LevelEditor *create_level_editor(Memory *memory, Cursor *cursor)
{
- Lt *lt = create_lt();
- LevelEditor *level_editor = PUSH_LT(
- lt,
- nth_calloc(1, sizeof(LevelEditor)),
- free);
- if (level_editor == NULL) {
- RETURN_LT(lt, NULL);
- }
- level_editor->lt = lt;
-
- level_editor->edit_field_filename = PUSH_LT(
- lt,
- create_edit_field(
- LEVEL_EDITOR_EDIT_FIELD_SIZE,
- LEVEL_EDITOR_EDIT_FIELD_COLOR),
- destroy_edit_field);
- if (level_editor->edit_field_filename == NULL) {
- RETURN_LT(lt, NULL);
- }
+ LevelEditor *level_editor = memory_alloc(memory, sizeof(LevelEditor));
+ memset(level_editor, 0, sizeof(*level_editor));
- 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));
-
- 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));
+ level_editor->edit_field_filename.font_size = LEVEL_EDITOR_EDIT_FIELD_SIZE;
+ level_editor->edit_field_filename.font_color = LEVEL_EDITOR_EDIT_FIELD_COLOR;
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->player_layer =
- create_player_layer(vec(0.0f, 0.0f), hexstr("ff8080"));
-
- level_editor->platforms_layer = PUSH_LT(
- lt,
- create_rect_layer("platform", cursor),
- destroy_rect_layer);
- if (level_editor->platforms_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->goals_layer = PUSH_LT(
- lt,
- create_point_layer("goal"),
- destroy_point_layer);
- if (level_editor->goals_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->lava_layer = PUSH_LT(
- lt,
- create_rect_layer("lava", cursor),
- destroy_rect_layer);
- if (level_editor->lava_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->back_platforms_layer = PUSH_LT(
- lt,
- create_rect_layer("back_platform", cursor),
- destroy_rect_layer);
- if (level_editor->back_platforms_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->boxes_layer = PUSH_LT(
- lt,
- create_rect_layer("box", cursor),
- destroy_rect_layer);
- if (level_editor->boxes_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->label_layer = PUSH_LT(
- lt,
- create_label_layer("label"),
- destroy_label_layer);
- if (level_editor->label_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->regions_layer = PUSH_LT(
- lt,
- create_rect_layer("region", cursor),
- destroy_rect_layer);
- if (level_editor->regions_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
+ 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->pp_layer = create_rect_layer(memory, "pp", 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_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_PP] = rect_layer_as_layer(level_editor->pp_layer);
+
level_editor->notice = (FadingWigglyText) {
.wiggly_text = {
};
level_editor->camera_scale = 1.0f;
+ level_editor->undo_history = create_undo_history(memory);
return level_editor;
}
-LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor)
+LevelEditor *create_level_editor_from_file(Memory *memory, Cursor *cursor, const char *file_name)
{
+ trace_assert(memory);
+ trace_assert(cursor);
trace_assert(file_name);
- Lt *lt = create_lt();
- LevelEditor *level_editor = PUSH_LT(
- lt,
- nth_calloc(1, sizeof(LevelEditor)),
- free);
- if (level_editor == NULL) {
- RETURN_LT(lt, NULL);
- }
- level_editor->lt = lt;
-
- level_editor->edit_field_filename = PUSH_LT(
- lt,
- create_edit_field(
- LEVEL_EDITOR_EDIT_FIELD_SIZE,
- LEVEL_EDITOR_EDIT_FIELD_COLOR),
- destroy_edit_field);
- if (level_editor->edit_field_filename == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->file_name =
- PUSH_LT(
- lt,
- string_duplicate(file_name, NULL),
- free);
-
- LineStream *level_stream = PUSH_LT(
- lt,
- create_line_stream(
- file_name,
- "r",
- LEVEL_LINE_MAX_LENGTH),
- destroy_line_stream);
- if (level_stream == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- if (metadata_load_from_line_stream(&level_editor->metadata, level_stream, level_editor->file_name) < 0) {
- RETURN_LT(lt, NULL);
- }
+ LevelEditor *level_editor = create_level_editor(memory, cursor);
+ level_editor->file_name = strdup_to_memory(memory, file_name);
- if (background_layer_read_from_line_stream(
- &level_editor->background_layer,
- level_stream) < 0) {
- RETURN_LT(lt, NULL);
- }
+ String input = read_whole_file(memory, file_name);
+ trace_assert(input.data);
- level_editor->player_layer =
- create_player_layer_from_line_stream(level_stream);
+ String version = trim(chop_by_delim(&input, '\n'));
- level_editor->platforms_layer =
- PUSH_LT(
- lt,
- create_rect_layer_from_line_stream(level_stream, "platform", cursor),
- destroy_rect_layer);
- if (level_editor->platforms_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->goals_layer = PUSH_LT(
- lt,
- create_point_layer_from_line_stream(level_stream, "goal"),
- destroy_point_layer);
- if (level_editor->goals_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->lava_layer =
- PUSH_LT(
- lt,
- create_rect_layer_from_line_stream(level_stream, "lava", cursor),
- destroy_rect_layer);
- if (level_editor->lava_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->back_platforms_layer =
- PUSH_LT(
- lt,
- create_rect_layer_from_line_stream(level_stream, "back_platform", cursor),
- destroy_rect_layer);
- if (level_editor->back_platforms_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->boxes_layer =
- PUSH_LT(
- lt,
- create_rect_layer_from_line_stream(level_stream, "box", cursor),
- destroy_rect_layer);
- if (level_editor->boxes_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->label_layer =
- PUSH_LT(
- lt,
- create_label_layer_from_line_stream(level_stream, "label"),
- destroy_label_layer);
- if (level_editor->label_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- level_editor->regions_layer =
- PUSH_LT(
- lt,
- create_rect_layer_from_line_stream(level_stream, "region", cursor),
- destroy_rect_layer);
- if (level_editor->regions_layer == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- 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_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->drag = false;
-
- level_editor->notice = (FadingWigglyText) {
- .wiggly_text = {
- .text = "Level saved",
- .color = rgba(0.0f, 0.0f, 0.0f, 0.0f),
- .scale = LEVEL_EDITOR_NOTICE_SCALE
- },
- .duration = LEVEL_EDITOR_NOTICE_DURATION,
- };
-
- level_editor->camera_scale = 1.0f;
+ if (string_equal(version, STRING_LIT("1"))) {
+ chop_by_delim(&input, '\n');
+ } else if (string_equal(version, STRING_LIT("2"))) {
+ // Nothing
+ } else {
+ log_fail("Version `%s` is not supported. Expected version `%s`.\n",
+ string_to_cstr(memory, version),
+ VERSION);
+ return NULL;
+ }
+
+ level_editor->background_layer = chop_background_layer(&input);
+ level_editor->player_layer = chop_player_layer(memory, &input);
+ level_editor->platforms_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ point_layer_load(level_editor->goals_layer, memory, &input);
+ level_editor->lava_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ level_editor->back_platforms_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ level_editor->boxes_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ label_layer_load(level_editor->label_layer, memory, &input);
+ level_editor->regions_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ level_editor->pp_layer = create_rect_layer_from_input(memory, &input, "", cursor);
+ undo_history_clean(level_editor->undo_history);
return level_editor;
}
-void destroy_level_editor(LevelEditor *level_editor)
-{
- trace_assert(level_editor);
- destroy_undo_history(level_editor->undo_history);
- RETURN_LT0(level_editor->lt);
-}
-
int level_editor_render(const LevelEditor *level_editor,
const Camera *camera)
{
position);
if (edit_field_render_screen(
- level_editor->edit_field_filename,
+ &level_editor->edit_field_filename,
camera,
vec(position.x + save_as_width, position.y)) < 0) {
return -1;
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);
snprintf(
path,
LEVEL_FOLDER_MAX_LENGTH,
- "./assets/levels//%s.txt",
- edit_field_as_text(level_editor->edit_field_filename));
- level_editor->file_name = PUSH_LT(
- level_editor->lt,
- string_duplicate(path, NULL),
- free);
+ "./assets/levels/%s.txt",
+ edit_field_as_text(&level_editor->edit_field_filename));
+ level_editor->file_name = strdup_to_memory(memory, path);
level_editor_dump(level_editor);
SDL_StopTextInput();
level_editor->state = LEVEL_EDITOR_IDLE;
} break;
}
- return edit_field_event(level_editor->edit_field_filename, event);
+ return edit_field_event(&level_editor->edit_field_filename, event);
}
static
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;
}
level_editor->layers[level_editor->layer_picker],
event,
camera,
- &level_editor->undo_history) < 0) {
+ level_editor->undo_history) < 0) {
return -1;
}
} else {
int level_editor_event(LevelEditor *level_editor,
const SDL_Event *event,
- Camera *camera)
+ Camera *camera,
+ Memory *memory)
{
trace_assert(level_editor);
trace_assert(event);
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;
LAYER_PICKER_BACK_PLATFORMS,
LAYER_PICKER_BOXES,
LAYER_PICKER_LABELS,
- LAYER_PICKER_REGIONS
+ LAYER_PICKER_REGIONS,
+ LAYER_PICKER_PP
};
/* TODO(#904): LevelEditor does not check that the saved level file is modified by external program */
{
trace_assert(level_editor);
- FILE *filedump = PUSH_LT(
- level_editor->lt,
- fopen(level_editor->file_name, "w"),
- fclose_lt);
-
- if (fprintf(filedump, "%s\n", level_editor->metadata.version) < 0) {
- return -1;
- }
+ FILE *filedump = fopen(level_editor->file_name, "w");
+ trace_assert(filedump);
- if (fprintf(filedump, "%s\n", level_editor->metadata.title) < 0) {
+ if (fprintf(filedump, "%s\n", VERSION) < 0) {
return -1;
}
}
}
- fclose(RELEASE_LT(level_editor->lt, filedump));
+ fclose(filedump);
fading_wiggly_text_reset(&level_editor->notice);
level_editor->save = 1;