diff --git a/freesprite/EditorColorPicker.h b/freesprite/EditorColorPicker.h index 89896d5..cb6b47d 100644 --- a/freesprite/EditorColorPicker.h +++ b/freesprite/EditorColorPicker.h @@ -25,25 +25,25 @@ class EditorColorPicker : public Drawable, public EventCallbackListener uint8_t currentR = 0, currentG = 0, currentB = 0; - UIHueSlider* hueSlider; - UISVPicker* satValSlider; - UITextField* colorTextField; - UISlider* sliderH; + UIHueSlider* hueSlider = NULL; + UISVPicker* satValSlider = NULL; + UITextField* colorTextField = NULL; + UISlider* sliderH = NULL; UITextField* txtR, *txtG, *txtB; UITextField* txtH, *txtS, *txtV; - UIColorSlider* sliderS; - UIColorSlider* sliderV; - UIColorSlider* sliderR; - UIColorSlider* sliderG; - UIColorSlider* sliderB; + UIColorSlider* sliderS = NULL; + UIColorSlider* sliderV = NULL; + UIColorSlider* sliderR = NULL; + UIColorSlider* sliderG = NULL; + UIColorSlider* sliderB = NULL; - TabbedView* colorModeTabs; - TabbedView* colorTabs; + TabbedView* colorModeTabs = NULL; + TabbedView* colorTabs = NULL; - UIButton* eraserButton; - UIButton* blendModeButton; + UIButton* eraserButton = NULL; + UIButton* blendModeButton = NULL; std::vector lastColors; bool lastColorsChanged = true; diff --git a/freesprite/FileIO.h b/freesprite/FileIO.h index f963c77..d13caf0 100644 --- a/freesprite/FileIO.h +++ b/freesprite/FileIO.h @@ -104,48 +104,87 @@ struct FileExportFlatNPath { }; }; -inline std::vector g_fileExportersFlatNPaths = { - { - "PNG (libpng)", ".png", &writePNG, FORMAT_RGB | FORMAT_PALETTIZED - }, - { - "RPG2000/2003 XYZ (voidsprite custom)", ".xyz", &writeXYZ, FORMAT_RGB | FORMAT_PALETTIZED - }, - { - "BMP (EasyBMP)", ".bmp", &writeBMP - }, - { - "TGA (voidsprite custom)", ".tga", &writeTGA - }, - { - "CaveStory PBM (EasyBMP)", ".pbm", &writeCaveStoryPBM - }, - { - "C Header (voidsprite custom)", ".h", &writeCHeader - }, - { - "Python NumPy array (voidsprite custom)", ".py", &writePythonNPArray - }, - { - "HTML Base64 image (base64)", ".html", &writeHTMLBase64 - }, - { - "Java Buffered Image (voidsprite custom)", ".java", &writeJavaBufferedImage +class FileExporter { + +public: + static FileExporter* sessionExporter(std::string name, std::string extension, bool (*exportFunction)(PlatformNativePathString, MainEditor*), int formatflags = FORMAT_RGB, bool (*canExport)(MainEditor*) = NULL) { + FileExporter* ret = new FileExporter(); + ret->_name = name; + ret->_extension = extension; + ret->_formatFlags = formatflags; + ret->_isSessionExporter = true; + ret->_sessionExportFunction = exportFunction; + ret->_sessionCheckExportFunction = canExport; + return ret; } -}; -inline std::vector g_fileExportersMLNPaths = { - { - "voidsprite Session version 3", ".voidsn", &writeVOIDSNv3 - }, - { - "voidsprite Session version 2", ".voidsnv2", &writeVOIDSNv2 - }, - { - "OpenRaster", ".ora", &writeOpenRaster + static FileExporter* flatExporter(std::string name, std::string extension, bool (*exportFunction)(PlatformNativePathString, Layer*), int formatflags = FORMAT_RGB, bool (*canExport)(Layer*) = NULL) { + FileExporter* ret = new FileExporter(); + ret->_name = name; + ret->_extension = extension; + ret->_formatFlags = formatflags; + ret->_isSessionExporter = false; + ret->_flatExportFunction = exportFunction; + ret->_flatCheckExportFunction = canExport; + return ret; + } + + virtual int formatFlags() { return _formatFlags; } + virtual std::string name() { return _name; } + virtual std::string extension() { return _extension; } + virtual bool exportsWholeSession() { return _isSessionExporter; } + virtual bool canExport(void* data) { + if (exportsWholeSession()) { + return _sessionCheckExportFunction != NULL ? _sessionCheckExportFunction((MainEditor*)data) : true; + } + else { + return _flatCheckExportFunction != NULL ? _flatCheckExportFunction((Layer*)data) : true; + } } + virtual bool exportData(PlatformNativePathString path, void* data) { + if (exportsWholeSession()) { + return _sessionExportFunction(path, (MainEditor*)data); + } + else { + return _flatExportFunction(path, (Layer*)data); + } + } +protected: + std::string _name = "File type (library)"; + std::string _extension = ""; + int _formatFlags = FORMAT_RGB; + bool _isSessionExporter = false; + + bool (*_sessionExportFunction)(PlatformNativePathString, MainEditor*) = NULL; + bool (*_sessionCheckExportFunction)(MainEditor*) = NULL; + + bool (*_flatExportFunction)(PlatformNativePathString, Layer*) = NULL; + bool (*_flatCheckExportFunction)(Layer*) = NULL; }; +inline std::vector g_fileExporters; +inline std::vector g_palettizedFileExporters; +inline void g_setupIO() { + g_fileExporters.push_back(FileExporter::sessionExporter("voidsprite Session version 3", ".voidsn", &writeVOIDSNv3)); + g_fileExporters.push_back(FileExporter::sessionExporter("voidsprite Session version 2", ".voidsnv2", &writeVOIDSNv2)); + g_fileExporters.push_back(FileExporter::sessionExporter("OpenRaster", ".ora", &writeOpenRaster)); + + g_fileExporters.push_back(FileExporter::flatExporter("PNG (libpng)", ".png", &writePNG, FORMAT_RGB | FORMAT_PALETTIZED)); + g_fileExporters.push_back(FileExporter::flatExporter("RPG2000/2003 XYZ (voidsprite custom)", ".xyz", &writeXYZ, FORMAT_RGB | FORMAT_PALETTIZED)); + g_fileExporters.push_back(FileExporter::flatExporter("BMP (EasyBMP)", ".bmp", &writeBMP)); + g_fileExporters.push_back(FileExporter::flatExporter("TGA (voidsprite custom)", ".tga", &writeTGA)); + g_fileExporters.push_back(FileExporter::flatExporter("CaveStory PBM (EasyBMP)", ".pbm", &writeCaveStoryPBM)); + g_fileExporters.push_back(FileExporter::flatExporter("C Header (voidsprite custom)", ".h", &writeCHeader)); + g_fileExporters.push_back(FileExporter::flatExporter("Python NumPy array (voidsprite custom)", ".py", &writePythonNPArray)); + g_fileExporters.push_back(FileExporter::flatExporter("HTML Base64 image (base64)", ".html", &writeHTMLBase64)); + g_fileExporters.push_back(FileExporter::flatExporter("Java Buffered Image (voidsprite custom)", ".java", &writeJavaBufferedImage)); + + for (auto& exporter : g_fileExporters) { + if (exporter->formatFlags() & FORMAT_PALETTIZED) { + g_palettizedFileExporters.push_back(exporter); + } + } +} inline std::vector g_fileSessionImportersNPaths = { { diff --git a/freesprite/MainEditorPalettized.cpp b/freesprite/MainEditorPalettized.cpp index 997f7cb..95b689a 100644 --- a/freesprite/MainEditorPalettized.cpp +++ b/freesprite/MainEditorPalettized.cpp @@ -67,37 +67,21 @@ MainEditorPalettized::MainEditorPalettized(std::vector layers) void MainEditorPalettized::eventFileSaved(int evt_id, PlatformNativePathString name, int exporterId) { if (evt_id == EVENT_PALETTIZEDEDITOR_SAVEFILE) { - //todo clean this shit up - std::vector palettizedExporterIds; - std::vector> namesAndExtensions; - int cexporterID = 0; - for (auto& e : g_fileExportersMLNPaths) { - if ((e.exportFormats & FORMAT_PALETTIZED) != 0) { - palettizedExporterIds.push_back(cexporterID); - } - cexporterID++; - } - for (auto& e : g_fileExportersFlatNPaths) { - if ((e.exportFormats & FORMAT_PALETTIZED) != 0) { - palettizedExporterIds.push_back(cexporterID); - } - cexporterID++; - } - int actualExporterID = palettizedExporterIds[exporterId - 1]; + exporterId--; bool result = false; - if (actualExporterID >= g_fileExportersMLNPaths.size()) { - actualExporterID -= g_fileExportersMLNPaths.size(); - auto exporter = g_fileExportersFlatNPaths[actualExporterID]; - Layer* flat = flattenImageWithoutConvertingToRGB(); - result = exporter.exportFunction(name, flat); - delete flat; - } - else { - auto exporter = g_fileExportersMLNPaths[actualExporterID]; - result = exporter.exportFunction(name, this); + if (exporterId < g_palettizedFileExporters.size()) { + FileExporter* actualExporterID = g_palettizedFileExporters[exporterId]; + if (actualExporterID->exportsWholeSession()) { + result = actualExporterID->exportData(name, this); + } + else { + Layer* flat = flattenImageWithoutConvertingToRGB(); + result = actualExporterID->exportData(name, flat); + delete flat; + } } if (result) { @@ -497,22 +481,11 @@ void MainEditorPalettized::trySavePalettizedImage() void MainEditorPalettized::trySaveAsPalettizedImage() { lastWasSaveAs = true; - std::vector palettizedExporterIds; std::vector> namesAndExtensions; - int exporterID = 0; - for (auto& e : g_fileExportersMLNPaths) { - if ((e.exportFormats & FORMAT_PALETTIZED) != 0) { - namesAndExtensions.push_back({ e.extension, e.name }); - palettizedExporterIds.push_back(exporterID); - } - exporterID++; - } - for (auto& e : g_fileExportersFlatNPaths) { - if ((e.exportFormats & FORMAT_PALETTIZED) != 0) { - namesAndExtensions.push_back({ e.extension, e.name }); - palettizedExporterIds.push_back(exporterID); + for (auto& e : g_palettizedFileExporters) { + if ((e->formatFlags() & FORMAT_PALETTIZED) != 0) { + namesAndExtensions.push_back({ e->extension(), e->name()}); } - exporterID++; } platformTrySaveOtherFile(this, namesAndExtensions, "save palettized image", EVENT_PALETTIZEDEDITOR_SAVEFILE); } diff --git a/freesprite/PopupQuickConvert.cpp b/freesprite/PopupQuickConvert.cpp index b01c7d8..5d5245e 100644 --- a/freesprite/PopupQuickConvert.cpp +++ b/freesprite/PopupQuickConvert.cpp @@ -19,11 +19,8 @@ PopupQuickConvert::PopupQuickConvert(std::string tt, std::string tx) { wxsManager.addDrawable(nbutton); std::vector formats; - for (auto& fmt : g_fileExportersFlatNPaths) { - formats.push_back(fmt.name); - } - for (auto& fmt : g_fileExportersMLNPaths) { - formats.push_back(fmt.name); + for (auto& fmt : g_fileExporters) { + formats.push_back(fmt->name()); } exporterIndex = 0; @@ -72,34 +69,20 @@ void PopupQuickConvert::onDropFileEvent(SDL_Event evt) MainEditor* session = loadAnyIntoSession(path); if (session != NULL) { - if (exporterIndex >= g_fileExportersFlatNPaths.size()) { - int realExporterIndex = exporterIndex - g_fileExportersFlatNPaths.size(); - FileExportMultiLayerNPath exporter = g_fileExportersMLNPaths[realExporterIndex]; - /*Layer* l; + FileExporter* exporter = g_fileExporters[exporterIndex]; - if (session->isPalettized) { - if ((exporter.exportFormats & FORMAT_PALETTIZED) != 0) { - MainEditorPalettized* upcastSession = (MainEditorPalettized*)session; - l = upcastSession->flattenImageWithoutConvertingToRGB(); - } - else { - MainEditorPalettized* upcastSession = (MainEditorPalettized*)session; - l = upcastSession->flattenImageAndConvertToRGB(); - } - } - else { - l = session->flattenImage(); - }*/ - if (session->isPalettized && ((exporter.exportFormats & FORMAT_PALETTIZED) == 0)) { + if (exporter->exportsWholeSession()) { + + if (session->isPalettized && ((exporter->formatFlags() & FORMAT_PALETTIZED) == 0)) { MainEditor* rgbConvEditor = ((MainEditorPalettized*)session)->toRGBSession(); delete session; session = rgbConvEditor; } - outPath += convertStringOnWin32(exporter.extension); + outPath += convertStringOnWin32(exporter->extension()); - if (exporter.exportFunction(outPath, session)) { + if (exporter->exportData(outPath, session)) { g_addNotification(Notification("Success", "Exported file", 4000, NULL, COLOR_INFO)); } else { @@ -107,12 +90,10 @@ void PopupQuickConvert::onDropFileEvent(SDL_Event evt) } } else { - FileExportFlatNPath exporter = g_fileExportersFlatNPaths[exporterIndex]; - Layer* l = NULL; if (session->isPalettized) { - if ((exporter.exportFormats & FORMAT_PALETTIZED) != 0) { + if ((exporter->formatFlags() & FORMAT_PALETTIZED) != 0) { MainEditorPalettized* upcastSession = (MainEditorPalettized*)session; l = upcastSession->flattenImageWithoutConvertingToRGB(); } @@ -125,9 +106,9 @@ void PopupQuickConvert::onDropFileEvent(SDL_Event evt) l = session->flattenImage(); } - outPath += convertStringOnWin32(exporter.extension); + outPath += convertStringOnWin32(exporter->extension()); - if (exporter.exportFunction(outPath, l)) { + if (exporter->exportData(outPath, l)) { g_addNotification(Notification("Success", "Exported file", 4000, NULL, COLOR_INFO)); } else { diff --git a/freesprite/main.cpp b/freesprite/main.cpp index c934a4e..bfd2537 100644 --- a/freesprite/main.cpp +++ b/freesprite/main.cpp @@ -19,6 +19,7 @@ #include "ToolRectSwap.h" #include "ToolText.h" #include "Gamepad.h" +#include "FileIO.h" #include "ee_creature.h" @@ -218,6 +219,8 @@ int main(int argc, char** argv) g_gamepad = new Gamepad(); g_gamepad->TryCaptureGamepad(); + g_setupIO(); + //load brushes g_brushes.push_back(new Brush1x1()); g_brushes.push_back(new Brush1x1ArcX()); diff --git a/freesprite/maineditor.cpp b/freesprite/maineditor.cpp index c094c6e..fee06eb 100644 --- a/freesprite/maineditor.cpp +++ b/freesprite/maineditor.cpp @@ -850,15 +850,18 @@ void MainEditor::eventFileSaved(int evt_id, PlatformNativePathString name, int e printf("eventFileSaved: got file name %ls\n", name.c_str()); bool result = false; - if (exporterID >= g_fileExportersMLNPaths.size()) { - FileExportFlatNPath f = g_fileExportersFlatNPaths[exporterID - g_fileExportersMLNPaths.size()]; - Layer* flat = flattenImage(); - result = f.exportFunction(name, flat); - delete flat; - } - else { - FileExportMultiLayerNPath f = g_fileExportersMLNPaths[exporterID]; - result = f.exportFunction(name, this); + + if (exporterID < g_fileExporters.size()) { + FileExporter* exporter = g_fileExporters[exporterID]; + + if (exporter->exportsWholeSession()) { + result = exporter->exportData(name, this); + } + else { + Layer* flat = flattenImage(); + result = exporter->exportData(name, flat); + delete flat; + } } if (result) { @@ -978,11 +981,8 @@ void MainEditor::trySaveAsImage() { lastWasSaveAs = true; std::vector> formats; - for (FileExportMultiLayerNPath f : g_fileExportersMLNPaths) { - formats.push_back({ f.extension, f.name }); - } - for (FileExportFlatNPath f : g_fileExportersFlatNPaths) { - formats.push_back({ f.extension, f.name }); + for (auto f : g_fileExporters) { + formats.push_back({ f->extension(), f->name()}); } platformTrySaveOtherFile(this, formats, "save image", EVENT_MAINEDITOR_SAVEFILE); } diff --git a/freesprite/platform_windows.h b/freesprite/platform_windows.h index 5ad26e0..44eac44 100644 --- a/freesprite/platform_windows.h +++ b/freesprite/platform_windows.h @@ -52,96 +52,9 @@ void platformPostInit() { d3dobject->Release(); } -void platformTrySaveImageFile(EventCallbackListener* listener) { - OPENFILENAMEW ofna; - ZeroMemory(&ofna, sizeof(ofna)); - ofna.lStructSize = sizeof(ofna); - ofna.hwndOwner = WINhWnd; - std::wstring filterString = L""; - std::vector filterStrings; - for (FileExportMultiLayerNPath f : g_fileExportersMLNPaths) { - filterString += utf8StringToWstring(f.name) + std::format(L"({})", utf8StringToWstring(f.extension)); - filterString.push_back('\0'); - filterString += L"*" + utf8StringToWstring(f.extension); - filterString.push_back('\0'); - filterStrings.push_back(utf8StringToWstring(f.extension)); - } - for (FileExportFlatNPath f : g_fileExportersFlatNPaths) { - filterString += utf8StringToWstring(f.name) + std::format(L"({})", utf8StringToWstring(f.extension)); - filterString.push_back('\0'); - filterString += L"*" + utf8StringToWstring(f.extension); - filterString.push_back('\0'); - filterStrings.push_back(utf8StringToWstring(f.extension)); - } - 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; - ofna.lpstrTitle = L"voidsprite: Save Image"; - ofna.lpstrDefExt = L"png"; - if (GetSaveFileNameW(&ofna)) { - - lastFilterIndex = ofna.nFilterIndex; - std::wstring fileName = fileNameBuffer; - std::wstring fileNameLower = fileName; - std::transform(fileNameLower.begin(), fileNameLower.end(), fileNameLower.begin(), ::tolower); - - std::wstring extension = filterStrings[ofna.nFilterIndex - 1]; - if (fileNameLower.size() < extension.size() || fileNameLower.substr(fileNameLower.size() - extension.size()) != extension) { - fileName += extension; - } - listener->eventFileSaved(EVENT_MAINEDITOR_SAVEFILE, fileName, ofna.nFilterIndex); - } - else { - printf("windows error: %i\n", GetLastError()); - } -} +void platformTrySaveImageFile(EventCallbackListener* listener) {} -void platformTryLoadImageFile(EventCallbackListener* listener) { - OPENFILENAMEW ofna; - ZeroMemory(&ofna, sizeof(ofna)); - ofna.lStructSize = sizeof(ofna); - ofna.hwndOwner = WINhWnd; - std::wstring filterString = L""; - std::vector filterStrings; - for (FileSessionImportNPath f : g_fileSessionImportersNPaths) { - filterString += utf8StringToWstring(f.name) + std::format(L"({})", utf8StringToWstring(f.extension)); - filterString.push_back('\0'); - filterString += L"*" + utf8StringToWstring(f.extension); - filterString.push_back('\0'); - filterStrings.push_back(utf8StringToWstring(f.extension)); - } - for (FileImportNPath f : g_fileImportersNPaths) { - filterString += utf8StringToWstring(f.name) + std::format(L"({})", utf8StringToWstring(f.extension)); - filterString.push_back('\0'); - filterString += L"*" + utf8StringToWstring(f.extension); - filterString.push_back('\0'); - filterStrings.push_back(utf8StringToWstring(f.extension)); - } - 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; - ofna.lpstrTitle = L"voidsprite: Open Image"; - ofna.lpstrDefExt = L"png"; - if (GetOpenFileNameW(&ofna)) { - std::wstring fileName = fileNameBuffer; - listener->eventFileOpen(EVENT_MAINEDITOR_SAVEFILE, fileName, ofna.nFilterIndex); - } - else { - printf("windows error: %i\n", GetLastError()); - } -} +void platformTryLoadImageFile(EventCallbackListener* listener) {} //pairs in format {extension, name}