Mario Editor: add option to select a level to load

This commit is contained in:
zv0n 2022-07-24 20:22:45 +02:00
parent 6cee97059c
commit 4477c39524
5 changed files with 301 additions and 12 deletions

View File

@ -92,6 +92,7 @@ target_sources(editor
PRIVATE scenes/editor_main_menu.cpp PRIVATE scenes/editor_main_menu.cpp
PRIVATE scenes/yes_no_scene.cpp PRIVATE scenes/yes_no_scene.cpp
PRIVATE scenes/ok_scene.cpp PRIVATE scenes/ok_scene.cpp
PRIVATE scenes/load_scene.cpp
) )
target_compile_definitions(editor PUBLIC EDITOR) target_compile_definitions(editor PUBLIC EDITOR)

View File

@ -13,6 +13,7 @@
#include "../blocks/coineditorblock.hpp" #include "../blocks/coineditorblock.hpp"
#include <SDL2/SDL_keycode.h> #include <SDL2/SDL_keycode.h>
#include <array> #include <array>
#include "../filesystem.hpp"
#ifdef _WIN32 #ifdef _WIN32
#include "../sdlpp/SDL2/SDL2_framerate.h" #include "../sdlpp/SDL2/SDL2_framerate.h"
@ -46,6 +47,8 @@
#define MOD_WIDTH 2 #define MOD_WIDTH 2
#define OVERWORLD_WIDTH 2 #define OVERWORLD_WIDTH 2
const std::string levelsDir = "levels";
struct ToolType { struct ToolType {
enum Value { enum Value {
BLOCK, BLOCK,
@ -142,12 +145,14 @@ bool getFlag(uint64_t flag) {
void saveMapCallback(void * /*UNUSED*/, Button * /*UNUSED*/) { void saveMapCallback(void * /*UNUSED*/, Button * /*UNUSED*/) {
std::cout << "SAVING" << std::endl; std::cout << "SAVING" << std::endl;
saveMap("levels/" + level_name_text + ".marmap", global_vars.objects); saveMap(levelsDir + FSLib::dir_divisor + level_name_text + ".marmap",
global_vars.objects);
} }
void loadMapDialogCallback(const std::string &level_name) {
void loadMapDialogCallback(void * /*UNUSED*/, Button * /*UNUSED*/) {
std::cout << "LOADING" << std::endl; std::cout << "LOADING" << std::endl;
level_name_text = level_name.substr(0, level_name.length() - 7);
setFlag(LOAD_MAP_FLAG); setFlag(LOAD_MAP_FLAG);
setFlag(TEXT_UPDATE_FLAG);
} }
void updateTool() { void updateTool() {
@ -1023,7 +1028,7 @@ void populateWorldType(
scene->addObject(tool_text); scene->addObject(tool_text);
} }
void enableTextInput(void */*UNUSED*/, Button */*UNUSED*/) { void enableTextInput(void * /*UNUSED*/, Button * /*UNUSED*/) {
setFlag(TEXT_INPUT_FLAG); setFlag(TEXT_INPUT_FLAG);
SDL_StartTextInput(); SDL_StartTextInput();
} }
@ -1042,11 +1047,11 @@ void openMapEditor(std::shared_ptr<SDLPP::Scene> &scene,
global_vars.current_world_type = LandType::OVERWORLD; global_vars.current_world_type = LandType::OVERWORLD;
if (filename.empty()) { if (filename.empty() || !FSLib::exists(filename)) {
loadEmptyMap(global_vars.objects, MAP_WIDTH); loadEmptyMap(global_vars.objects, MAP_WIDTH);
} else { } else {
loadMap(scene, global_vars.mario, "test_binary.bin", loadMap(scene, global_vars.mario, filename, global_vars.objects, true,
global_vars.objects, true, MAP_WIDTH); MAP_WIDTH);
} }
// map // map
@ -1146,7 +1151,8 @@ void openMapEditor(std::shared_ptr<SDLPP::Scene> &scene,
// level_name label // level_name label
auto level_name_label = std::make_shared<SDLPP::TextRenderer>( auto level_name_label = std::make_shared<SDLPP::TextRenderer>(
0.1, 0.1, BLOCK_SIZE * 8, 0.05, renderer, "Level Name:", font_config, SDLPP_TEXT_LEFT); 0.1, 0.1, BLOCK_SIZE * 8, 0.05, renderer, "Level Name:", font_config,
SDLPP_TEXT_LEFT);
level_name_label->setAlignment(SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER); level_name_label->setAlignment(SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER);
level_name_label->setPermanent(); level_name_label->setPermanent();
scene->addObject(level_name_label); scene->addObject(level_name_label);
@ -1335,9 +1341,9 @@ void editorAdditionalRender(std::shared_ptr<SDLPP::Scene> &scene) {
unsetFlag(UPDATE_FLAG); unsetFlag(UPDATE_FLAG);
} }
if (getFlag(LOAD_MAP_FLAG)) { if (getFlag(LOAD_MAP_FLAG)) {
// TODO filename
editorScene->resetScene(); editorScene->resetScene();
openMapEditor(editorScene, "test_binary.bin"); openMapEditor(editorScene, levelsDir + FSLib::dir_divisor +
level_name_text + ".marmap");
unsetFlag(LOAD_MAP_FLAG); unsetFlag(LOAD_MAP_FLAG);
} }
if (getFlag(TEXT_UPDATE_FLAG)) { if (getFlag(TEXT_UPDATE_FLAG)) {

View File

@ -29,6 +29,17 @@ void resumeMainMenuCallback(void * /*UNUSED*/, Button * /*UNUSED*/) {
resumeMainMenu(); resumeMainMenu();
} }
void loadFinished(const std::string level_name) {
__quit_scenes_main_menu = true;
loadMapDialogCallback(level_name);
}
void showLoadMenu(void */*UNUSED*/, Button */*UNUSED*/) {
// TODO levels
auto loadMenu = createLoadScene(__buttons_main_menu.back()->getRenderer(), "levels", loadFinished);
game_scenes.push_back(loadMenu);
}
void __updateSelectedButton_MainMenu(uint64_t new_index) { void __updateSelectedButton_MainMenu(uint64_t new_index) {
if (new_index != __cur_button_index_main_menu && if (new_index != __cur_button_index_main_menu &&
new_index != (uint64_t)-1) { new_index != (uint64_t)-1) {
@ -120,7 +131,7 @@ createSceneMainMenu(std::shared_ptr<SDLPP::Renderer> &renderer) {
__buttons_main_menu.back()->setButtonIndex(__buttons_main_menu.size() - 1); __buttons_main_menu.back()->setButtonIndex(__buttons_main_menu.size() - 1);
__buttons_main_menu.emplace_back(std::make_shared<Button>( __buttons_main_menu.emplace_back(std::make_shared<Button>(
0.2, 0.4, 0.6, 0.1, renderer, "LOAD", default_button_theme, 0.2, 0.4, 0.6, 0.1, renderer, "LOAD", default_button_theme,
loadMapDialogCallback, nullptr)); showLoadMenu, nullptr));
__buttons_main_menu.back()->setAlignment(SDLPP::OBJ_CENTER, __buttons_main_menu.back()->setAlignment(SDLPP::OBJ_CENTER,
SDLPP::OBJ_CENTER); SDLPP::OBJ_CENTER);
__buttons_main_menu.back()->setPermanent(); __buttons_main_menu.back()->setPermanent();

View File

@ -15,7 +15,7 @@ extern std::mutex render_mutex;
extern std::vector<SceneStruct> game_scenes; extern std::vector<SceneStruct> game_scenes;
void saveMapCallback(void *input, Button *caller); void saveMapCallback(void *input, Button *caller);
void loadMapDialogCallback(void *input, Button *caller); void loadMapDialogCallback(const std::string &level_name);
SceneStruct createEditorScene(std::shared_ptr<SDLPP::Renderer> &renderer); SceneStruct createEditorScene(std::shared_ptr<SDLPP::Renderer> &renderer);
SceneStruct SceneStruct
@ -29,5 +29,8 @@ SceneStruct createYesNoScene(std::shared_ptr<SDLPP::Renderer> renderer,
SceneStruct createOkScene(std::shared_ptr<SDLPP::Renderer> renderer, SceneStruct createOkScene(std::shared_ptr<SDLPP::Renderer> renderer,
const std::string &text, const std::string &text,
std::function<void()> finalizer); std::function<void()> finalizer);
SceneStruct createLoadScene(std::shared_ptr<SDLPP::Renderer> renderer,
const std::string &path,
std::function<void(const std::string &)> finalizer);
#endif #endif

268
mario/scenes/load_scene.cpp Normal file
View File

@ -0,0 +1,268 @@
#include "SDL2/SDL_keycode.h"
#include "editor_scenes.hpp"
#include "../../sdlpp/sdlpp.hpp"
#include "../../sdlpp/sdlpp_mouse.hpp"
#include "../global_vars.hpp"
#include "../objectids.hpp"
#include "../editor_visitor.hpp"
#include "../filesystem.hpp"
bool __update_scenes_load_dialog = false;
bool __quit_scenes_load_dialog = false;
bool __started_load_dialog = false;
uint64_t __cur_button_index_load_dialog = -1;
uint64_t __cur_button_index_load_dialog_down = -1;
std::vector<std::shared_ptr<Button>> __buttons_load_dialog{};
std::shared_ptr<SDLPP::RectangleRender> __mouse_load_dialog{};
std::function<void(const std::string &)> __load_dialog_finalizer;
std::string __selected_level_load_dialog = "";
void __quitLoadDialog() {
__quit_scenes_load_dialog = true;
}
void __updateSelectedButton_LoadDialog(uint64_t new_index) {
if (new_index != __cur_button_index_load_dialog &&
new_index != (uint64_t)-1) {
__buttons_load_dialog[new_index]->setHighlight();
if (__cur_button_index_load_dialog != (uint64_t)-1) {
__buttons_load_dialog[__cur_button_index_load_dialog]
->unsetHighlight();
}
__cur_button_index_load_dialog = new_index;
}
}
void __quitCallback_LoadDialog(void * /*UNUSED*/, Button *btn) {
__selected_level_load_dialog = btn->getText();
__quitLoadDialog();
}
void __moveButtons(double movement) {
for (auto &button : __buttons_load_dialog) {
button->setPos(button->getPos() + SDLPP::Vec2D<double>(0, movement));
}
__update_scenes_load_dialog = true;
}
void __selectUpperButton() {
if (__cur_button_index_load_dialog > 0) {
__updateSelectedButton_LoadDialog(__cur_button_index_load_dialog - 1);
if (__buttons_load_dialog[__cur_button_index_load_dialog]
->getPos()
.getY() < 0.49) {
__moveButtons(0.25);
}
}
}
void __selectLowerButton() {
if (__cur_button_index_load_dialog < __buttons_load_dialog.size() - 1) {
__updateSelectedButton_LoadDialog(__cur_button_index_load_dialog + 1);
auto pos =
__buttons_load_dialog[__cur_button_index_load_dialog]->getPos();
if (__buttons_load_dialog[__cur_button_index_load_dialog]
->getPos()
.getY() > 0.99) {
__moveButtons(-0.25);
}
}
}
void __handleKeyUp_LoadDialog(SDL_Keycode key, SDLPP::Scene & /*UNUSED*/) {
switch (key) {
case SDLK_ESCAPE:
__selected_level_load_dialog = "";
__quitLoadDialog();
break;
case SDLK_RETURN:
__buttons_load_dialog[__cur_button_index_load_dialog]
->performFunction();
break;
case SDLK_UP:
case SDLK_w:
__selectUpperButton();
break;
case SDLK_DOWN:
case SDLK_s:
__selectLowerButton();
break;
default:
break;
}
}
void addLevelButton(const std::string &path, const std::string &file,
double &start_height, const int initial_path_len,
std::shared_ptr<SDLPP::Renderer> &renderer,
ButtonConfig &button_theme) {
if (FSLib::isDirectory(path + FSLib::dir_divisor + file)) {
for (const auto &file_rec :
FSLib::Directory(path + FSLib::dir_divisor + file)) {
addLevelButton(path + FSLib::dir_divisor + file, file_rec,
start_height, initial_path_len, renderer,
button_theme);
}
} else {
__buttons_load_dialog.emplace_back(std::make_shared<Button>(
0.3, start_height, 0.4, 0.2, renderer,
(path + FSLib::dir_divisor + file).substr(initial_path_len),
button_theme, __quitCallback_LoadDialog, nullptr));
__buttons_load_dialog.back()->setAlignment(SDLPP::OBJ_CENTER,
SDLPP::OBJ_CENTER);
__buttons_load_dialog.back()->setPermanent();
__buttons_load_dialog.back()->setButtonIndex(
__buttons_load_dialog.size() - 1);
start_height += 0.25;
}
}
std::shared_ptr<SDLPP::Scene>
createSceneLoadDialog(std::shared_ptr<SDLPP::Renderer> &renderer,
const std::string &path) {
auto scene = std::make_shared<SDLPP::Scene>(renderer);
auto bg = std::make_shared<SDLPP::RectangleRender>(0, 0, 10, 10, renderer,
"#000000BB", true);
bg->setPermanent();
bg->setId(1);
scene->addObject(bg);
__mouse_load_dialog =
std::make_shared<SDLPP::RectangleRender>(0.01, 0.01, 0, 0, renderer);
__mouse_load_dialog->setMinWidth(1);
__mouse_load_dialog->setMinHeight(1);
__mouse_load_dialog->setAlignment(SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER);
__mouse_load_dialog->setId(EDITOR_MOUSE_ID);
__mouse_load_dialog->setColiderColor("#00FF00");
__mouse_load_dialog->addCollision(SDLPP::RectColider({ 0, 0 }, { 1, 1 }));
scene->addObject(__mouse_load_dialog);
ButtonConfig default_button_theme{};
default_button_theme.bg_color = "#FFFFFF88";
default_button_theme.bg_color_highlight = "#FFFFFFBB";
default_button_theme.bg_color_disabled = "#AAAAAA88";
default_button_theme.font_color = "#000000";
default_button_theme.font_color_highlight = "#000000";
default_button_theme.font_color_disabled = "#555555";
default_button_theme.font_outline_color = "#FFFFFF88";
default_button_theme.font_outline_color_highlight = "#FFFFFFAA";
default_button_theme.font_outline_color_disabled = "#787878";
default_button_theme.outline = 0.1;
// buttons
double start_height = 0.5;
for (const auto &file : FSLib::Directory(path)) {
addLevelButton(path, file, start_height, path.length() + 1, renderer,
default_button_theme);
}
for (auto &button : __buttons_load_dialog) {
scene->addObject(button);
}
auto font_config = std::make_shared<SDLPP::FontConfiguration>(
g_text_config->getFont(), "#000000", "#282828", 0.05);
auto dialog_text = std::make_shared<SDLPP::TextRenderer>(
0.1, 0.15, 0.8, 0.3, renderer, "LEVELS", font_config,
SDLPP_TEXT_CENTER);
dialog_text->setAlignment(SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER);
dialog_text->setPermanent();
scene->addObject(dialog_text);
return scene;
}
void __resetGlobals_LoadDialog() {
__update_scenes_load_dialog = false;
__quit_scenes_load_dialog = false;
__started_load_dialog = false;
__cur_button_index_load_dialog = -1;
__cur_button_index_load_dialog_down = -1;
__buttons_load_dialog.clear();
__mouse_load_dialog.reset();
__selected_level_load_dialog = "";
}
void __additionalRender_LoadDialog(std::shared_ptr<SDLPP::Scene> & /*UNUSED*/) {
if (__update_scenes_load_dialog) {
for (auto &_scene : game_scenes) {
_scene.scene->updateSizeAndPosition();
}
if (__started_load_dialog) {
__update_scenes_load_dialog = false;
} else {
__started_load_dialog = true;
}
}
if (__quit_scenes_load_dialog) {
__load_dialog_finalizer(__selected_level_load_dialog);
game_scenes.pop_back();
__resetGlobals_LoadDialog();
}
}
void __getMousePositionFlags_LoadDialog(SDLPP::Scene &scene) {
auto mouse = scene.getObjects({ EDITOR_MOUSE_ID })[0];
// move mouse colider to mouse position
mouse->setPos(SDLPP::Mouse::getMousePositionDouble(
scene.getRenderer(), SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER));
MouseVisitor visitor;
scene.visitCollisions(*mouse, visitor);
__updateSelectedButton_LoadDialog(visitor.getCurButton());
//__cur_button_index_load_dialog = visitor.getCurButton();
}
void __pollEvents_LoadDialog(std::shared_ptr<SDLPP::Scene> &scene) {
SDL_Event event;
while (SDLPP::getSDLEvent(event)) {
switch (event.type) {
case SDL_QUIT:
__quitLoadDialog();
break;
case SDL_KEYUP:
__handleKeyUp_LoadDialog(event.key.keysym.sym, *scene);
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
__update_scenes_load_dialog = true;
}
break;
case SDL_MOUSEMOTION:
__getMousePositionFlags_LoadDialog(*scene);
break;
case SDL_MOUSEBUTTONUP:
if (__cur_button_index_load_dialog_down ==
__cur_button_index_load_dialog &&
__cur_button_index_load_dialog != (uint64_t)-1) {
__buttons_load_dialog[__cur_button_index_load_dialog]
->performFunction();
}
break;
case SDL_MOUSEBUTTONDOWN:
// store current mouse flags in previous mouse flags
__cur_button_index_load_dialog_down =
__cur_button_index_load_dialog;
break;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) {
__moveButtons(-0.02);
} else if (event.wheel.y < 0) {
__moveButtons(0.02);
}
break;
default:
break;
}
}
}
SceneStruct
createLoadScene(std::shared_ptr<SDLPP::Renderer> renderer,
const std::string &path,
std::function<void(const std::string &)> finalizer) {
__load_dialog_finalizer = finalizer;
SceneStruct ret{};
ret.scene = createSceneLoadDialog(renderer, path);
ret.additionalRender = __additionalRender_LoadDialog;
ret.doInput = __pollEvents_LoadDialog;
__update_scenes_load_dialog = true;
__updateSelectedButton_LoadDialog(0);
return ret;
}