mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
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:
parent
273d2901a5
commit
2bd5ed28d6
36
src/Menus.c
36
src/Menus.c
@ -1279,15 +1279,15 @@ static struct SaveLevelScreen {
|
|||||||
struct FontDesc titleFont, textFont;
|
struct FontDesc titleFont, textFont;
|
||||||
struct ButtonWidget save, alt, cancel;
|
struct ButtonWidget save, alt, cancel;
|
||||||
struct TextInputWidget input;
|
struct TextInputWidget input;
|
||||||
struct TextWidget mcEdit, desc;
|
struct TextWidget desc;
|
||||||
} SaveLevelScreen;
|
} SaveLevelScreen;
|
||||||
|
|
||||||
static struct Widget* save_widgets[6] = {
|
static struct Widget* save_widgets[] = {
|
||||||
(struct Widget*)&SaveLevelScreen.save, (struct Widget*)&SaveLevelScreen.alt,
|
(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,
|
(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) {
|
static void SaveLevelScreen_UpdateSave(struct SaveLevelScreen* s) {
|
||||||
ButtonWidget_SetConst(&s->save,
|
ButtonWidget_SetConst(&s->save,
|
||||||
@ -1352,7 +1352,7 @@ static void SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string*
|
|||||||
res = Cw_Save(&compStream);
|
res = Cw_Save(&compStream);
|
||||||
#else
|
#else
|
||||||
if (String_CaselessEnds(path, &cw)) {
|
if (String_CaselessEnds(path, &cw)) {
|
||||||
res = Cw_Save(&compStream);
|
res = Cw_Save(&compStream); /* TODO change to checking for schematic instead */
|
||||||
} else {
|
} else {
|
||||||
res = Schematic_Save(&compStream);
|
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 */
|
/* 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"); }
|
static void SaveLevelScreen_Alt(void* a, void* b) { SaveLevelScreen_Save(a, b, "/%s.tmpmap"); }
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
static void SaveLevelScreen_Render(void* screen, double delta) {
|
static void SaveLevelScreen_Render(void* screen, double delta) {
|
||||||
@ -1468,9 +1486,6 @@ static void SaveLevelScreen_ContextRecreated(void* screen) {
|
|||||||
SaveLevelScreen_UpdateSave(s);
|
SaveLevelScreen_UpdateSave(s);
|
||||||
SaveLevelScreen_UpdateAlt(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);
|
TextInputWidget_SetFont(&s->input, &s->textFont);
|
||||||
ButtonWidget_SetConst(&s->cancel, "Cancel", &s->titleFont);
|
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);
|
Widget_SetLocation(&s->alt, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 70);
|
||||||
#else
|
#else
|
||||||
Widget_SetLocation(&s->alt, ANCHOR_CENTRE, ANCHOR_CENTRE, -150, 120);
|
Widget_SetLocation(&s->alt, ANCHOR_CENTRE, ANCHOR_CENTRE, -150, 120);
|
||||||
Widget_SetLocation(&s->mcEdit, ANCHOR_CENTRE, ANCHOR_CENTRE, 110, 120);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Menu_LayoutBack(&s->cancel);
|
Menu_LayoutBack(&s->cancel);
|
||||||
@ -1511,10 +1525,8 @@ static void SaveLevelScreen_Init(void* screen) {
|
|||||||
ButtonWidget_Init(&s->save, 300, SaveLevelScreen_Main);
|
ButtonWidget_Init(&s->save, 300, SaveLevelScreen_Main);
|
||||||
#ifdef CC_BUILD_WEB
|
#ifdef CC_BUILD_WEB
|
||||||
ButtonWidget_Init(&s->alt, 300, SaveLevelScreen_Alt);
|
ButtonWidget_Init(&s->alt, 300, SaveLevelScreen_Alt);
|
||||||
s->widgets[2] = NULL; /* null mcEdit widget */
|
|
||||||
#else
|
#else
|
||||||
ButtonWidget_Init(&s->alt, 200, SaveLevelScreen_Alt);
|
ButtonWidget_Init(&s->alt, 200, SaveLevelScreen_Alt);
|
||||||
TextWidget_Init(&s->mcEdit);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ButtonWidget_Init(&s->cancel, 400, Menu_SwitchPause);
|
ButtonWidget_Init(&s->cancel, 400, Menu_SwitchPause);
|
||||||
|
11
src/Window.h
11
src/Window.h
@ -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_DELETE 0 /* (webclient) Deletes the uploaded file after invoking callback function */
|
||||||
#define OFD_UPLOAD_PERSIST 1 /* (webclient) Saves the uploded file into IndexedDB */
|
#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 {
|
struct OpenFileDialogArgs {
|
||||||
const char* description; /* Describes the types of files supported (e.g. "Texture packs") */
|
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) */
|
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 */
|
int uploadAction; /* Action webclient takes after invoking callback function */
|
||||||
const char* uploadFolder; /* For webclient, folder to upload the file to */
|
const char* uploadFolder; /* For webclient, folder to upload the file to */
|
||||||
};
|
};
|
||||||
/* Shows an 'load file' dialog window */
|
/* Shows an 'load file' dialog window */
|
||||||
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args);
|
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. */
|
/* Allocates a framebuffer that can be drawn/transferred to the window. */
|
||||||
/* NOTE: Do NOT free bmp->Scan0, use Window_FreeFramebuffer. */
|
/* NOTE: Do NOT free bmp->Scan0, use Window_FreeFramebuffer. */
|
||||||
|
@ -595,6 +595,10 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
|
|||||||
return ERR_NOT_SUPPORTED;
|
return ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
|
||||||
|
return ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
static CGrafPtr fb_port;
|
static CGrafPtr fb_port;
|
||||||
static struct Bitmap fb_bmp;
|
static struct Bitmap fb_bmp;
|
||||||
static CGColorSpaceRef colorSpace;
|
static CGColorSpaceRef colorSpace;
|
||||||
|
@ -281,6 +281,10 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
|
|||||||
return ERR_NOT_SUPPORTED;
|
return ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
|
||||||
|
return ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_Surface* win_surface;
|
static SDL_Surface* win_surface;
|
||||||
static SDL_Surface* blit_surface;
|
static SDL_Surface* blit_surface;
|
||||||
|
|
||||||
|
@ -551,52 +551,78 @@ static void ShowDialogCore(const char* title, const char* msg) {
|
|||||||
MessageBoxA(win_handle, msg, title, 0);
|
MessageBoxA(win_handle, msg, title, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
|
static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load) {
|
||||||
const char* const* filters = args->filters;
|
|
||||||
cc_string path; char pathBuffer[NATIVE_STR_LEN];
|
cc_string path; char pathBuffer[NATIVE_STR_LEN];
|
||||||
WCHAR str[MAX_PATH] = { 0 };
|
WCHAR str[MAX_PATH] = { 0 };
|
||||||
OPENFILENAMEW ofn = { 0 };
|
OPENFILENAMEW ofn = { 0 };
|
||||||
WCHAR filter[MAX_PATH];
|
WCHAR filter[MAX_PATH];
|
||||||
|
BOOL ok;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */
|
Platform_EncodeUtf16(filter, filters);
|
||||||
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);
|
|
||||||
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = win_handle;
|
ofn.hwndOwner = win_handle;
|
||||||
ofn.lpstrFile = str;
|
ofn.lpstrFile = str;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
ofn.lpstrFilter = filter;
|
ofn.lpstrFilter = filter;
|
||||||
ofn.nFilterIndex = 1;
|
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))
|
ok = load ? GetOpenFileNameW(&ofn) : GetSaveFileNameW(&ofn);
|
||||||
return CommDlgExtendedError();
|
if (!ok) return CommDlgExtendedError();
|
||||||
String_InitArray(path, pathBuffer);
|
String_InitArray(path, pathBuffer);
|
||||||
|
|
||||||
for (i = 0; i < MAX_PATH && str[i]; i++) {
|
for (i = 0; i < MAX_PATH && str[i]; i++) {
|
||||||
String_Append(&path, Convert_CodepointToCP437(str[i]));
|
String_Append(&path, Convert_CodepointToCP437(str[i]));
|
||||||
}
|
}
|
||||||
args->Callback(&path);
|
callback(&path);
|
||||||
return 0;
|
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 HDC draw_DC;
|
||||||
static HBITMAP draw_DIB;
|
static HBITMAP draw_DIB;
|
||||||
void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user