From d8ae3fb268a0e2d825b0f2446ca36d3025d38435 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:30:56 +0200 Subject: [PATCH] save tile layouts --- freesprite/EventCallbackListener.h | 2 + freesprite/TilemapPreviewScreen.cpp | 109 ++++++++++++++++++++++++++-- freesprite/TilemapPreviewScreen.h | 8 +- freesprite/platform.h | 2 + freesprite/platform_windows.h | 81 +++++++++++++++++++++ 5 files changed, 195 insertions(+), 7 deletions(-) diff --git a/freesprite/EventCallbackListener.h b/freesprite/EventCallbackListener.h index 55f74ae..3d1110b 100644 --- a/freesprite/EventCallbackListener.h +++ b/freesprite/EventCallbackListener.h @@ -17,6 +17,8 @@ #define EVENT_COLORPICKER_SLIDERR 14 #define EVENT_COLORPICKER_SLIDERG 15 #define EVENT_COLORPICKER_SLIDERB 16 +#define EVENT_OTHERFILE_SAVEFILE 17 +#define EVENT_OTHERFILE_OPENFILE 18 class EventCallbackListener { public: diff --git a/freesprite/TilemapPreviewScreen.cpp b/freesprite/TilemapPreviewScreen.cpp index 91b1e38..3dff848 100644 --- a/freesprite/TilemapPreviewScreen.cpp +++ b/freesprite/TilemapPreviewScreen.cpp @@ -1,9 +1,39 @@ #include "TilemapPreviewScreen.h" #include "maineditor.h" #include "FontRenderer.h" +#include "ScreenWideNavBar.h" +#include "Notification.h" TilemapPreviewScreen::TilemapPreviewScreen(MainEditor* parent) { caller = parent; + + navbar = new ScreenWideNavBar(this, + { + { + SDLK_f, + { + "File", + {}, + { + {SDLK_o, { "Load layout from file", + [](TilemapPreviewScreen* screen) { + platformTryLoadOtherFile(screen, ".voidtile", "Load tile layout"); + } + } + }, + {SDLK_s, { "Save layout to file", + [](TilemapPreviewScreen* screen) { + platformTrySaveOtherFile(screen, ".voidtile", "Save tile layout"); + } + } + }, + }, + g_iconNavbarTabFile + } + } + }, { SDLK_f }); + wxsManager.addDrawable(navbar); + resizeTilemap(32, 32); tileSelectScale = caller->scale; @@ -61,14 +91,14 @@ void TilemapPreviewScreen::render() SDL_RenderDrawRect(g_rd, &tilemapSelectedTile); SDL_SetRenderDrawColor(g_rd, 0, 0, 0, 0xa0); - SDL_Rect panelRect = { 0,0, ixmax(400, 30 + caller->tileDimensions.x * tilemapScale * 2), ixmax(200, 110 + caller->tileDimensions.y * tilemapScale * 2)}; + SDL_Rect panelRect = { 0,40, ixmax(400, 30 + caller->tileDimensions.x * tilemapScale * 2), ixmax(200, 110 + caller->tileDimensions.y * tilemapScale * 2)}; SDL_RenderFillRect(g_rd, &panelRect); - g_fnt->RenderString("Tileset preview", 5, 5); - g_fnt->RenderString("Selected tile: [TAB] to switch", 15, 60); + g_fnt->RenderString("Tileset preview", panelRect.x + 5, panelRect.y+5); + g_fnt->RenderString("Selected tile: [TAB] to switch", panelRect.x + 15, panelRect.y + 60); SDL_Rect tileDraw = { - 15, - 90, + panelRect.x + 15, + panelRect.y + 90, caller->tileDimensions.x * tilemapScale*2, caller->tileDimensions.y * tilemapScale*2 }; @@ -124,6 +154,13 @@ void TilemapPreviewScreen::render() g_fnt->RenderString("Select tile...", 10, 10); } + + if (navbar->focused) { + SDL_SetRenderDrawColor(g_rd, 0, 0, 0, 0x80); + SDL_RenderFillRect(g_rd, NULL); + } + + wxsManager.renderAll(); } void TilemapPreviewScreen::tick() @@ -152,7 +189,7 @@ void TilemapPreviewScreen::takeInput(SDL_Event evt) g_closeScreen(this); return; } - if (evt.type == SDL_MOUSEBUTTONDOWN && evt.button.button == 1 && evt.button.state) { + if (evt.type == SDL_MOUSEBUTTONDOWN && evt.button.state) { wxsManager.tryFocusOnPoint(XY{ evt.button.x, evt.button.y }); } @@ -224,6 +261,9 @@ void TilemapPreviewScreen::takeInput(SDL_Event evt) tileSelectOpen = !tileSelectOpen; tileSelectTimer.start(); } + else if (evt.key.keysym.sym == SDLK_LALT) { + wxsManager.forceFocusOn(navbar); + } break; } } @@ -237,6 +277,63 @@ BaseScreen* TilemapPreviewScreen::isSubscreenOf() return caller; } +void TilemapPreviewScreen::eventFileSaved(int evt_id, PlatformNativePathString name, int exporterIndex) +{ + FILE* file = platformOpenFile(name, PlatformFileModeWB); + if (file == NULL) { + g_addNotification(Notification("Error saving file", "Could not open file for writing.")); + return; + } + else { + uint8_t version = 1; + fwrite(&version, 1, 1, file); + fwrite(&tilemapDimensions.x, 4, 1, file); + fwrite(&tilemapDimensions.y, 4, 1, file); + for (int y = 0; y < tilemapDimensions.y; y++) { + for (int x = 0; x < tilemapDimensions.x; x++) { + XY td = tilemap[y][x]; + fwrite(&td.x, 4, 1, file); + fwrite(&td.y, 4, 1, file); + } + } + fclose(file); + g_addNotification(Notification("File saved", "Save successful!", 4000)); + } +} + +void TilemapPreviewScreen::eventFileOpen(int evt_id, PlatformNativePathString name, int importerIndex) +{ + FILE* file = platformOpenFile(name, PlatformFileModeRB); + if (file == NULL) { + g_addNotification(Notification("Error loading file", "Could not open file for writing.")); + return; + } + else { + uint8_t version; + fread(&version, 1, 1, file); + switch (version) { + case 1: + XY dims; + fread(&dims.x, 4, 1, file); + fread(&dims.y, 4, 1, file); + resizeTilemap(dims.x, dims.y); + for (int y = 0; y < tilemapDimensions.y; y++) { + for (int x = 0; x < tilemapDimensions.x; x++) { + XY td; + fread(&td.x, 4, 1, file); + fread(&td.y, 4, 1, file); + tilemap[y][x] = td; + } + } + break; + default: + g_addNotification(Notification("Error loading file", "File version not supported")); + break; + } + fclose(file); + } +} + void TilemapPreviewScreen::resizeTilemap(int w, int h) { XY** newTilemap = (XY**)malloc(h * sizeof(XY*)); diff --git a/freesprite/TilemapPreviewScreen.h b/freesprite/TilemapPreviewScreen.h index 56208a7..67e785f 100644 --- a/freesprite/TilemapPreviewScreen.h +++ b/freesprite/TilemapPreviewScreen.h @@ -1,8 +1,9 @@ #pragma once #include "BaseScreen.h" #include "DrawableManager.h" +#include "EventCallbackListener.h" -class TilemapPreviewScreen : public BaseScreen +class TilemapPreviewScreen : public BaseScreen, EventCallbackListener { public: MainEditor* caller; @@ -26,6 +27,8 @@ class TilemapPreviewScreen : public BaseScreen int tileSelectScale = 1; Timer64 tileSelectTimer; + ScreenWideNavBar* navbar; + TilemapPreviewScreen(MainEditor* parent); void render() override; @@ -35,6 +38,9 @@ class TilemapPreviewScreen : public BaseScreen std::string getName() override { return "Preview tiles"; } + virtual void eventFileSaved(int evt_id, PlatformNativePathString name, int exporterIndex = -1) override; + virtual void eventFileOpen(int evt_id, PlatformNativePathString name, int importerIndex = -1) override; + void resizeTilemap(int w, int h); void drawBackground(); void recenterTilemap(); diff --git a/freesprite/platform.h b/freesprite/platform.h index 5757063..8b29eb3 100644 --- a/freesprite/platform.h +++ b/freesprite/platform.h @@ -18,6 +18,8 @@ void platformPostInit(); void platformTrySaveImageFile(EventCallbackListener* caller); void platformTryLoadImageFile(EventCallbackListener* caller); +void platformTrySaveOtherFile(EventCallbackListener* caller, std::string extension, std::string windowTitle = "Save file"); +void platformTryLoadOtherFile(EventCallbackListener* caller, std::string extension, std::string windowTitle = "Open file"); void platformOpenFileLocation(PlatformNativePathString path); FILE* platformOpenFile(PlatformNativePathString path, PlatformNativePathString mode); \ No newline at end of file diff --git a/freesprite/platform_windows.h b/freesprite/platform_windows.h index bb198d1..80e8507 100644 --- a/freesprite/platform_windows.h +++ b/freesprite/platform_windows.h @@ -146,6 +146,87 @@ void platformTryLoadImageFile(EventCallbackListener* listener) { } } + +void platformTrySaveOtherFile(EventCallbackListener* listener, std::string extension, std::string windowTitle) { + OPENFILENAMEW ofna; + ZeroMemory(&ofna, sizeof(ofna)); + ofna.lStructSize = sizeof(ofna); + ofna.hwndOwner = WINhWnd; + std::wstring filterString = L""; + filterString += utf8StringToWstring(extension) + L" file"; + filterString.push_back('\0'); + filterString += L"*" + utf8StringToWstring(extension); + filterString.push_back('\0'); + filterString.push_back('\0'); + ofna.lpstrFilter = filterString.c_str(); + ofna.lpstrCustomFilter = NULL; + ofna.nFilterIndex = lastFilterIndex; + ofna.lpstrFile = fileNameBuffer; + ofna.nMaxFile = MAX_PATH; + ofna.lpstrFileTitle = NULL; + ofna.lpstrInitialDir = NULL; + ofna.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT; + + std::wstring windowTitleW = L"voidsprite: " + utf8StringToWstring(windowTitle); + ofna.lpstrTitle = windowTitleW.c_str(); + + std::wstring extensionW = utf8StringToWstring(extension); + std::wstring extensionWtr = extensionW.substr(1); + ofna.lpstrDefExt = extensionWtr.c_str(); + + if (GetSaveFileNameW(&ofna)) { + lastFilterIndex = ofna.nFilterIndex; + std::wstring fileName = fileNameBuffer; + if (fileName.size() < extensionW.size() || fileName.substr(fileName.size() - extensionW.size()) != extensionW) { + fileName += extensionW; + } + listener->eventFileSaved(EVENT_OTHERFILE_SAVEFILE, fileName, ofna.nFilterIndex); + } + else { + printf("windows error: %i\n", GetLastError()); + } +} + +void platformTryLoadOtherFile(EventCallbackListener* listener, std::string extension, std::string windowTitle) { + OPENFILENAMEW ofna; + ZeroMemory(&ofna, sizeof(ofna)); + ofna.lStructSize = sizeof(ofna); + ofna.hwndOwner = WINhWnd; + std::wstring filterString = L""; + filterString += utf8StringToWstring(extension) + L" file"; + filterString.push_back('\0'); + filterString += L"*" + utf8StringToWstring(extension); + filterString.push_back('\0'); + filterString.push_back('\0'); + ofna.lpstrFilter = filterString.c_str(); + ofna.lpstrCustomFilter = NULL; + ofna.nFilterIndex = lastFilterIndex; + ofna.lpstrFile = fileNameBuffer; + ofna.nMaxFile = MAX_PATH; + ofna.lpstrFileTitle = NULL; + ofna.lpstrInitialDir = NULL; + ofna.Flags = OFN_EXPLORER; + + std::wstring windowTitleW = L"voidsprite: " + utf8StringToWstring(windowTitle); + ofna.lpstrTitle = windowTitleW.c_str(); + + std::wstring extensionW = utf8StringToWstring(extension); + std::wstring extensionWtr = extensionW.substr(1); + ofna.lpstrDefExt = extensionWtr.c_str(); + + if (GetOpenFileNameW(&ofna)) { + lastFilterIndex = ofna.nFilterIndex; + std::wstring fileName = fileNameBuffer; + if (fileName.size() < extensionW.size() || fileName.substr(fileName.size() - extensionW.size()) != extensionW) { + fileName += extensionW; + } + listener->eventFileOpen(EVENT_OTHERFILE_OPENFILE, fileName, ofna.nFilterIndex); + } + else { + printf("windows error: %i\n", GetLastError()); + } +} + void platformOpenFileLocation(PlatformNativePathString path) { std::wstring command = L"explorer /select,\""; command += path;