WIP on save file dialog support, that allows saving a map to anywhere on disc as either a .cw or a .schematic

This commit is contained in:
UnknownShadow200 2022-11-09 23:05:23 +11:00
parent 273d2901a5
commit 2bd5ed28d6
5 changed files with 92 additions and 39 deletions

View File

@ -1279,15 +1279,15 @@ static struct SaveLevelScreen {
struct FontDesc titleFont, textFont;
struct ButtonWidget save, alt, cancel;
struct TextInputWidget input;
struct TextWidget mcEdit, desc;
struct TextWidget desc;
} SaveLevelScreen;
static struct Widget* save_widgets[6] = {
static struct Widget* save_widgets[] = {
(struct Widget*)&SaveLevelScreen.save, (struct Widget*)&SaveLevelScreen.alt,
(struct Widget*)&SaveLevelScreen.mcEdit, (struct Widget*)&SaveLevelScreen.cancel,
(struct Widget*)&SaveLevelScreen.cancel,
(struct Widget*)&SaveLevelScreen.input, (struct Widget*)&SaveLevelScreen.desc,
};
#define SAVE_MAX_VERTICES (3 * BUTTONWIDGET_MAX + MENUINPUTWIDGET_MAX + 2 * TEXTWIDGET_MAX)
#define SAVE_MAX_VERTICES (3 * BUTTONWIDGET_MAX + MENUINPUTWIDGET_MAX + TEXTWIDGET_MAX)
static void SaveLevelScreen_UpdateSave(struct SaveLevelScreen* s) {
ButtonWidget_SetConst(&s->save,
@ -1352,7 +1352,7 @@ static void SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string*
res = Cw_Save(&compStream);
#else
if (String_CaselessEnds(path, &cw)) {
res = Cw_Save(&compStream);
res = Cw_Save(&compStream); /* TODO change to checking for schematic instead */
} else {
res = Schematic_Save(&compStream);
}
@ -1413,7 +1413,25 @@ static void SaveLevelScreen_Main(void* a, void* b) { SaveLevelScreen_Save(a, b,
/* Use absolute path so data is written to memory filesystem instead of default filesystem */
static void SaveLevelScreen_Alt(void* a, void* b) { SaveLevelScreen_Save(a, b, "/%s.tmpmap"); }
#else
static void SaveLevelScreen_Alt(void* a, void* b) { SaveLevelScreen_Save(a, b, "maps/%s.schematic"); }
static void SaveLevelScreen_UploadCallback(const cc_string* path) {
SaveLevelScreen_SaveMap(NULL, path);
}
static void SaveLevelScreen_Alt(void* a, void* b) {
//SaveLevelScreen_Save(a, b, "maps/%s.schematic");
static const char* const titles[] = {
"ClassiCube map", "MineCraft schematic", NULL
};
static const char* const filters[] = {
".cw", ".schematic", NULL
};
static struct SaveFileDialogArgs args = {
filters, titles, SaveLevelScreen_UploadCallback
};
cc_result res = Window_SaveFileDialog(&args);
if (res) Logger_SimpleWarn(res, "showing save file dialog");
}
#endif
static void SaveLevelScreen_Render(void* screen, double delta) {
@ -1468,9 +1486,6 @@ static void SaveLevelScreen_ContextRecreated(void* screen) {
SaveLevelScreen_UpdateSave(s);
SaveLevelScreen_UpdateAlt(s);
#ifndef CC_BUILD_WEB
TextWidget_SetConst(&s->mcEdit, "&eCan be imported into MCEdit", &s->textFont);
#endif
TextInputWidget_SetFont(&s->input, &s->textFont);
ButtonWidget_SetConst(&s->cancel, "Cancel", &s->titleFont);
}
@ -1487,7 +1502,6 @@ static void SaveLevelScreen_Layout(void* screen) {
Widget_SetLocation(&s->alt, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 70);
#else
Widget_SetLocation(&s->alt, ANCHOR_CENTRE, ANCHOR_CENTRE, -150, 120);
Widget_SetLocation(&s->mcEdit, ANCHOR_CENTRE, ANCHOR_CENTRE, 110, 120);
#endif
Menu_LayoutBack(&s->cancel);
@ -1511,10 +1525,8 @@ static void SaveLevelScreen_Init(void* screen) {
ButtonWidget_Init(&s->save, 300, SaveLevelScreen_Main);
#ifdef CC_BUILD_WEB
ButtonWidget_Init(&s->alt, 300, SaveLevelScreen_Alt);
s->widgets[2] = NULL; /* null mcEdit widget */
#else
ButtonWidget_Init(&s->alt, 200, SaveLevelScreen_Alt);
TextWidget_Init(&s->mcEdit);
#endif
ButtonWidget_Init(&s->cancel, 400, Menu_SwitchPause);

View File

@ -131,17 +131,24 @@ CC_API void Window_ShowDialog(const char* title, const char* msg);
#define OFD_UPLOAD_DELETE 0 /* (webclient) Deletes the uploaded file after invoking callback function */
#define OFD_UPLOAD_PERSIST 1 /* (webclient) Saves the uploded file into IndexedDB */
typedef void (*OpenFileDialogCallback)(const cc_string* path);
typedef void (*FileDialogCallback)(const cc_string* path);
struct SaveFileDialogArgs {
const char* const* filters; /* File extensions to limit dialog to showing (e.g. ".zip", NULL) */
const char* const* titles; /* Descriptions to show for each file extension */
FileDialogCallback Callback;
};
struct OpenFileDialogArgs {
const char* description; /* Describes the types of files supported (e.g. "Texture packs") */
const char* const* filters; /* File extensions to limit dialog to showing (e.g. ".zip", NULL) */
OpenFileDialogCallback Callback;
FileDialogCallback Callback;
int uploadAction; /* Action webclient takes after invoking callback function */
const char* uploadFolder; /* For webclient, folder to upload the file to */
};
/* Shows an 'load file' dialog window */
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args);
/* Shows an 'save file' dialog window */
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args);
/* Allocates a framebuffer that can be drawn/transferred to the window. */
/* NOTE: Do NOT free bmp->Scan0, use Window_FreeFramebuffer. */

View File

@ -595,6 +595,10 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
static CGrafPtr fb_port;
static struct Bitmap fb_bmp;
static CGColorSpaceRef colorSpace;

View File

@ -281,6 +281,10 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
static SDL_Surface* win_surface;
static SDL_Surface* blit_surface;

View File

@ -551,52 +551,78 @@ static void ShowDialogCore(const char* title, const char* msg) {
MessageBoxA(win_handle, msg, title, 0);
}
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load) {
cc_string path; char pathBuffer[NATIVE_STR_LEN];
WCHAR str[MAX_PATH] = { 0 };
OPENFILENAMEW ofn = { 0 };
WCHAR filter[MAX_PATH];
BOOL ok;
int i;
/* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */
String_InitArray(path, pathBuffer);
String_Format1(&path, "%c (", args->description);
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ';');
String_Format1(&path, "*%c", filters[i]);
}
String_Append(&path, ')');
String_Append(&path, '\0');
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ';');
String_Format1(&path, "*%c", filters[i]);
}
String_Append(&path, '\0');
Platform_EncodeUtf16(filter, &path);
Platform_EncodeUtf16(filter, filters);
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = win_handle;
ofn.lpstrFile = str;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
ofn.Flags = OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | (load ? OFN_FILEMUSTEXIST : OFN_OVERWRITEPROMPT);
if (!GetOpenFileNameW(&ofn))
return CommDlgExtendedError();
ok = load ? GetOpenFileNameW(&ofn) : GetSaveFileNameW(&ofn);
if (!ok) return CommDlgExtendedError();
String_InitArray(path, pathBuffer);
for (i = 0; i < MAX_PATH && str[i]; i++) {
String_Append(&path, Convert_CodepointToCP437(str[i]));
}
args->Callback(&path);
callback(&path);
return 0;
}
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
cc_string str; char strBuffer[NATIVE_STR_LEN];
int i;
/* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */
String_InitArray(str, strBuffer);
String_Format1(&str, "%c (", args->description);
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&str, ';');
String_Format1(&str, "*%c", filters[i]);
}
String_Append(&str, ')');
String_Append(&str, '\0');
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&str, ';');
String_Format1(&str, "*%c", filters[i]);
}
String_Append(&str, '\0');
return OpenSaveFileDialog(&str, args->Callback, true);
}
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
const char* const* titles = args->titles;
const char* const* filters = args->filters;
cc_string str; char strBuffer[NATIVE_STR_LEN];
int i;
/* Filter tokens are \0 separated - e.g. "Map (*.cw)\0*.cw\0 */
String_InitArray(str, strBuffer);
for (i = 0; filters[i]; i++)
{
String_Format2(&str, "%c (*%c)", titles[i], filters[i]);
String_Append(&str, '\0');
String_Format1(&str, "*%c", filters[i]);
String_Append(&str, '\0');
}
return OpenSaveFileDialog(&str, args->Callback, false);
}
static HDC draw_DC;
static HBITMAP draw_DIB;
void Window_AllocFramebuffer(struct Bitmap* bmp) {