Merge pull request #927 from UnknownShadow200/LoadFile-Maps

Add support for loading maps through native open file dialog
This commit is contained in:
UnknownShadow200 2022-01-20 21:09:15 +11:00 committed by GitHub
commit b60d30a933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 171 additions and 15 deletions

View File

@ -21,7 +21,6 @@
cc_bool EnvRenderer_Legacy, EnvRenderer_Minimal; cc_bool EnvRenderer_Legacy, EnvRenderer_Minimal;
#define ENV_SMALL_VERTICES 4096
static float CalcBlendFactor(float x) { static float CalcBlendFactor(float x) {
/* return -0.05 + 0.22 * (Math_Log(x) * 0.25f); */ /* return -0.05 + 0.22 * (Math_Log(x) * 0.25f); */
double blend = -0.13 + 0.28 * (Math_Log(x) * 0.25); double blend = -0.13 + 0.28 * (Math_Log(x) * 0.25);

View File

@ -201,16 +201,18 @@ static struct Widget* list_widgets[10] = {
static void ListScreen_Layout(void* screen) { static void ListScreen_Layout(void* screen) {
struct ListScreen* s = (struct ListScreen*)screen; struct ListScreen* s = (struct ListScreen*)screen;
int i; int i;
for (i = 0; i < LIST_SCREEN_ITEMS; i++) { for (i = 0; i < LIST_SCREEN_ITEMS; i++) {
Widget_SetLocation(&s->btns[i], Widget_SetLocation(&s->btns[i],
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, (i - 2) * 50); ANCHOR_CENTRE, ANCHOR_CENTRE, 0, (i - 2) * 50);
} }
if (s->UploadClick) { if (s->UploadClick && Input_TouchMode) {
Widget_SetLocation(&s->done, ANCHOR_CENTRE_MIN, ANCHOR_MAX, -150, 25); Widget_SetLocation(&s->done, ANCHOR_CENTRE_MIN, ANCHOR_MAX, -150, 25);
Widget_SetLocation(&s->upload, ANCHOR_CENTRE_MAX, ANCHOR_MAX, -150, 25); Widget_SetLocation(&s->upload, ANCHOR_CENTRE_MAX, ANCHOR_MAX, -150, 25);
} else { } else {
Menu_LayoutBack(&s->done); Widget_SetLocation(&s->done, ANCHOR_CENTRE, ANCHOR_MAX, 0, 25);
Widget_SetLocation(&s->upload, ANCHOR_CENTRE, ANCHOR_MAX, 0, 70);
} }
Widget_SetLocation(&s->left, ANCHOR_CENTRE, ANCHOR_CENTRE, -220, 0); Widget_SetLocation(&s->left, ANCHOR_CENTRE, ANCHOR_CENTRE, -220, 0);
@ -384,7 +386,11 @@ static void ListScreen_ContextRecreated(void* screen) {
ListScreen_UpdatePage(s); ListScreen_UpdatePage(s);
if (!s->UploadClick) return; if (!s->UploadClick) return;
#ifdef CC_BUILD_WEB
ButtonWidget_SetConst(&s->upload, "Upload", &s->font); ButtonWidget_SetConst(&s->upload, "Upload", &s->font);
#else
ButtonWidget_SetConst(&s->upload, "Load file...", &s->font);
#endif
} }
static void ListScreen_Reload(struct ListScreen* s) { static void ListScreen_Reload(struct ListScreen* s) {
@ -1587,7 +1593,8 @@ static void TexturePackScreen_UploadCallback(const cc_string* path) {
} }
static void TexturePackScreen_UploadFunc(void* s, void* w) { static void TexturePackScreen_UploadFunc(void* s, void* w) {
Window_OpenFileDialog(".zip", TexturePackScreen_UploadCallback); static const char* const filters[] = { ".zip", NULL };
Window_OpenFileDialog(filters, TexturePackScreen_UploadCallback);
} }
#else #else
#define TexturePackScreen_UploadFunc NULL #define TexturePackScreen_UploadFunc NULL
@ -1764,14 +1771,14 @@ static void LoadLevelScreen_LoadEntries(struct ListScreen* s) {
StringsBuffer_Sort(&s->entries); StringsBuffer_Sort(&s->entries);
} }
#ifdef CC_BUILD_WEB
static void LoadLevelScreen_UploadCallback(const cc_string* path) { Map_LoadFrom(path); } static void LoadLevelScreen_UploadCallback(const cc_string* path) { Map_LoadFrom(path); }
static void LoadLevelScreen_UploadFunc(void* s, void* w) { static void LoadLevelScreen_UploadFunc(void* s, void* w) {
Window_OpenFileDialog(".cw", LoadLevelScreen_UploadCallback); static const char* const filters[] = {
".cw", ".dat", ".lvl", ".mine", ".fcm", NULL
};
cc_result res = Window_OpenFileDialog(filters, LoadLevelScreen_UploadCallback);
if (res) Logger_SimpleWarn(res, "showing open file dialog");
} }
#else
#define LoadLevelScreen_UploadFunc NULL
#endif
void LoadLevelScreen_Show(void) { void LoadLevelScreen_Show(void) {
struct ListScreen* s = &ListScreen; struct ListScreen* s = &ListScreen;

View File

@ -133,7 +133,7 @@ void Cursor_SetVisible(cc_bool visible);
CC_API void Window_ShowDialog(const char* title, const char* msg); CC_API void Window_ShowDialog(const char* title, const char* msg);
typedef void (*OpenFileDialogCallback)(const cc_string* path); typedef void (*OpenFileDialogCallback)(const cc_string* path);
/* Shows an 'load file' dialog window. */ /* Shows an 'load file' dialog window. */
cc_result Window_OpenFileDialog(const char* filter, OpenFileDialogCallback callback); cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback);
/* 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. */

View File

@ -363,6 +363,10 @@ static void ShowDialogCore(const char* title, const char* msg) {
(*env)->DeleteLocalRef(env, args[1].l); (*env)->DeleteLocalRef(env, args[1].l);
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
return ERR_NOT_SUPPORTED;
}
static struct Bitmap fb_bmp; static struct Bitmap fb_bmp;
void Window_AllocFramebuffer(struct Bitmap* bmp) { void Window_AllocFramebuffer(struct Bitmap* bmp) {
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");

View File

@ -607,6 +607,10 @@ static void ShowDialogCore(const char* title, const char* msg) {
showingDialog = false; showingDialog = false;
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
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;

View File

@ -272,6 +272,10 @@ static void ShowDialogCore(const char* title, const char* msg) {
SDL_ShowSimpleMessageBox(0, title, msg, win_handle); SDL_ShowSimpleMessageBox(0, title, msg, win_handle);
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
return ERR_NOT_SUPPORTED;
}
static SDL_Surface* surface; static SDL_Surface* surface;
void Window_AllocFramebuffer(struct Bitmap* bmp) { void Window_AllocFramebuffer(struct Bitmap* bmp) {
surface = SDL_GetWindowSurface(win_handle); surface = SDL_GetWindowSurface(win_handle);

View File

@ -545,11 +545,24 @@ EMSCRIPTEN_KEEPALIVE void Window_OnFileUploaded(const char* src) {
} }
extern void interop_OpenFileDialog(const char* filter); extern void interop_OpenFileDialog(const char* filter);
cc_result Window_OpenFileDialog(const char* filter, OpenFileDialogCallback callback) { cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_string path; char pathBuffer[NATIVE_STR_LEN];
char filter[NATIVE_STR_LEN];
int i;
/* Filter tokens are , separated - e.g. ".cw,.dat */
String_InitArray(path, pathBuffer);
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ',');
String_AppendConst(&path, filters[i]);
}
Platform_EncodeUtf8(filter, &path);
uploadCallback = callback; uploadCallback = callback;
/* Calls Window_OnFileUploaded on success */ /* Calls Window_OnFileUploaded on success */
interop_OpenFileDialog(filter); interop_OpenFileDialog(filter);
return ERR_NOT_SUPPORTED; return 0;
} }
void Window_AllocFramebuffer(struct Bitmap* bmp) { } void Window_AllocFramebuffer(struct Bitmap* bmp) { }

View File

@ -22,6 +22,7 @@
/* Hence the actual minimum supported OS is Windows 2000. This just avoids redeclaring structs. */ /* Hence the actual minimum supported OS is Windows 2000. This just avoids redeclaring structs. */
#endif #endif
#include <windows.h> #include <windows.h>
#include <commdlg.h>
/* https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelformat */ /* https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelformat */
#define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN #define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
@ -136,7 +137,8 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
/* Set before position change, in case mouse buttons changed when outside window */ /* Set before position change, in case mouse buttons changed when outside window */
Input_SetNonRepeatable(KEY_LMOUSE, wParam & 0x01); if (!(wParam & 0x01)) Input_SetReleased(KEY_LMOUSE);
//Input_SetNonRepeatable(KEY_LMOUSE, wParam & 0x01);
Input_SetNonRepeatable(KEY_RMOUSE, wParam & 0x02); Input_SetNonRepeatable(KEY_RMOUSE, wParam & 0x02);
Input_SetNonRepeatable(KEY_MMOUSE, wParam & 0x10); Input_SetNonRepeatable(KEY_MMOUSE, wParam & 0x10);
/* TODO: do we need to set XBUTTON1/XBUTTON2 here */ /* TODO: do we need to set XBUTTON1/XBUTTON2 here */
@ -535,6 +537,51 @@ 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 char* const* filters, OpenFileDialogCallback callback) {
cc_string path; char pathBuffer[NATIVE_STR_LEN];
WCHAR str[MAX_PATH] = { 0 };
OPENFILENAMEW ofn = { 0 };
WCHAR filter[MAX_PATH];
int i;
/* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */
String_InitArray(path, pathBuffer);
String_AppendConst(&path, "All supported files (");
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.hwndOwner = win_handle;
ofn.lpstrFile = str;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (!GetOpenFileNameW(&ofn))
return CommDlgExtendedError();
String_InitArray(path, pathBuffer);
for (i = 0; i < MAX_PATH && str[i]; i++) {
String_Append(&path, Convert_CodepointToCP437(str[i]));
}
callback(&path);
return 0;
}
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) {

View File

@ -10,6 +10,7 @@
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
#include <stdio.h>
#ifdef X_HAVE_UTF8_STRING #ifdef X_HAVE_UTF8_STRING
#define CC_BUILD_XIM #define CC_BUILD_XIM
@ -966,6 +967,46 @@ static void ShowDialogCore(const char* title, const char* msg) {
XFlush(m.dpy); /* flush so window disappears immediately */ XFlush(m.dpy); /* flush so window disappears immediately */
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_string path; char pathBuffer[1024];
char result[4096] = { 0 };
int len, i;
FILE* fp;
String_InitArray_NT(path, pathBuffer);
String_AppendConst(&path, "zenity --file-selection --file-filter='All supported files (");
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ',');
String_Format1(&path, "*%c", filters[i]);
}
String_AppendConst(&path, ") |");
for (i = 0; filters[i]; i++)
{
String_Format1(&path, " *%c", filters[i]);
}
String_AppendConst(&path, "'");
path.buffer[path.length] = '\0';
/* TODO this doesn't detect when Zenity doesn't exist */
fp = popen(path.buffer, "r");
if (!fp) return 0;
/* result is normally just one string */
while (fgets(result, sizeof(result), fp)) { }
len = String_Length(result);
if (len) {
String_InitArray(path, pathBuffer);
String_AppendUtf8(&path, result, len);
callback(&path);
}
pclose(fp);
return 0;
}
static GC fb_gc; static GC fb_gc;
static XImage* fb_image; static XImage* fb_image;
static struct Bitmap fb_bmp; static struct Bitmap fb_bmp;

View File

@ -114,7 +114,7 @@ void Clipboard_SetText(const cc_string* value) {
NSString* str; NSString* str;
Platform_EncodeUtf8(raw, value); Platform_EncodeUtf8(raw, value);
str = [[NSString alloc] initWithUTF8String:raw]; str = [NSString stringWithUTF8String:raw];
pasteboard = [NSPasteboard generalPasteboard]; pasteboard = [NSPasteboard generalPasteboard];
[pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
@ -299,7 +299,7 @@ void Window_SetTitle(const cc_string* title) {
NSString* str; NSString* str;
Platform_EncodeUtf8(raw, title); Platform_EncodeUtf8(raw, title);
str = [[NSString alloc] initWithUTF8String:raw]; str = [NSString stringWithUTF8String:raw];
[winHandle setTitle:str]; [winHandle setTitle:str];
[str release]; [str release];
} }
@ -507,6 +507,39 @@ void ShowDialogCore(const char* title, const char* msg) {
CFRelease(msgCF); CFRelease(msgCF);
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
NSOpenPanel* dlg = [NSOpenPanel openPanel];
NSArray* files;
NSString* str;
const char* src;
int len, i;
NSMutableArray* types = [NSMutableArray array];
for (i = 0; filters[i]; i++)
{
NSString* filter = [NSString stringWithUTF8String:filters[i]];
filter = [filter substringFromIndex:1];
[types addObject:filter];
}
[dlg setCanChooseFiles: YES];
[dlg setAllowedFileTypes:types];
if ([dlg runModal] != NSOKButton) return 0;
files = [dlg URLs];
if ([files count] < 1) return 0;
str = [[files objectAtIndex:0] path];
src = [str UTF8String];
len = String_Length(src);
cc_string path; char pathBuffer[NATIVE_STR_LEN];
String_InitArray(path, pathBuffer);
String_AppendUtf8(&path, src, len);
callback(&path);
return 0;
}
static struct Bitmap fb_bmp; static struct Bitmap fb_bmp;
void Window_AllocFramebuffer(struct Bitmap* bmp) { void Window_AllocFramebuffer(struct Bitmap* bmp) {
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");

View File

@ -260,6 +260,10 @@ void Window_LockLandscapeOrientation(cc_bool lock) {
[UIViewController attemptRotationToDeviceOrientation]; [UIViewController attemptRotationToDeviceOrientation];
} }
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
return ERR_NOT_SUPPORTED;
}
/*#########################################################################################################################* /*#########################################################################################################################*
*--------------------------------------------------------2D window--------------------------------------------------------* *--------------------------------------------------------2D window--------------------------------------------------------*