build raylib and raygui manually
This commit is contained in:
parent
ba3836fbfb
commit
3e52a42d88
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[submodule "3rd-party/raygui"]
|
||||||
|
path = 3rd-party/raygui
|
||||||
|
url = https://github.com/raysan5/raygui.git
|
||||||
|
[submodule "3rd-party/raylib"]
|
||||||
|
path = 3rd-party/raylib
|
||||||
|
url = https://github.com/raysan5/raylib.git
|
5
3rd-party/Tupfile
vendored
Normal file
5
3rd-party/Tupfile
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
BDIR := ../build/raygui
|
||||||
|
|
||||||
|
: raygui.c |> clang -c %f -o %o -I../build/raylib/include -Iraygui/src |> $(BDIR)/%B.o
|
||||||
|
: $(BDIR)/*.o |> ar crs %o %f |> $(BDIR)/libraygui.a
|
||||||
|
|
738
3rd-party/gui_window_file_dialog.h
vendored
738
3rd-party/gui_window_file_dialog.h
vendored
|
@ -1,738 +0,0 @@
|
||||||
/*******************************************************************************************
|
|
||||||
*
|
|
||||||
* Window File Dialog v1.2 - Modal file dialog to open/save files
|
|
||||||
*
|
|
||||||
* MODULE USAGE:
|
|
||||||
* #define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
|
|
||||||
* #include "gui_window_file_dialog.h"
|
|
||||||
*
|
|
||||||
* INIT: GuiWindowFileDialogState state = GuiInitWindowFileDialog();
|
|
||||||
* DRAW: GuiWindowFileDialog(&state);
|
|
||||||
*
|
|
||||||
* NOTE: This module depends on some raylib file system functions:
|
|
||||||
* - LoadDirectoryFiles()
|
|
||||||
* - UnloadDirectoryFiles()
|
|
||||||
* - GetWorkingDirectory()
|
|
||||||
* - DirectoryExists()
|
|
||||||
* - FileExists()
|
|
||||||
*
|
|
||||||
* LICENSE: zlib/libpng
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019-2023 Ramon Santamaria (@raysan5)
|
|
||||||
*
|
|
||||||
* This software is provided "as-is", without any express or implied warranty.
|
|
||||||
*In no event will the authors be held liable for any damages arising from the
|
|
||||||
*use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
*including commercial applications, and to alter it and redistribute it freely,
|
|
||||||
*subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
*claim that you wrote the original software. If you use this software in a
|
|
||||||
*product, an acknowledgment in the product documentation would be appreciated
|
|
||||||
*but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
*be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
*distribution.
|
|
||||||
*
|
|
||||||
**********************************************************************************************/
|
|
||||||
|
|
||||||
#include "raylib.h"
|
|
||||||
|
|
||||||
#ifndef GUI_WINDOW_FILE_DIALOG_H
|
|
||||||
#define GUI_WINDOW_FILE_DIALOG_H
|
|
||||||
|
|
||||||
// Gui file dialog context data
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
// Window management variables
|
|
||||||
bool windowActive;
|
|
||||||
Rectangle windowBounds;
|
|
||||||
Vector2 panOffset;
|
|
||||||
bool dragMode;
|
|
||||||
bool supportDrag;
|
|
||||||
|
|
||||||
// UI variables
|
|
||||||
bool dirPathEditMode;
|
|
||||||
char dirPathText[1024];
|
|
||||||
|
|
||||||
int filesListScrollIndex;
|
|
||||||
bool filesListEditMode;
|
|
||||||
int filesListActive;
|
|
||||||
|
|
||||||
bool fileNameEditMode;
|
|
||||||
char fileNameText[1024];
|
|
||||||
bool SelectFilePressed;
|
|
||||||
bool CancelFilePressed;
|
|
||||||
int fileTypeActive;
|
|
||||||
int itemFocused;
|
|
||||||
|
|
||||||
// Custom state variables
|
|
||||||
FilePathList dirFiles;
|
|
||||||
char filterExt[256];
|
|
||||||
char dirPathTextCopy[1024];
|
|
||||||
char fileNameTextCopy[1024];
|
|
||||||
|
|
||||||
int prevFilesListActive;
|
|
||||||
|
|
||||||
bool saveFileMode;
|
|
||||||
|
|
||||||
} GuiWindowFileDialogState;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// ...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Declaration
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath);
|
|
||||||
void GuiWindowFileDialog(GuiWindowFileDialogState *state);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // GUI_WINDOW_FILE_DIALOG_H
|
|
||||||
|
|
||||||
/***********************************************************************************
|
|
||||||
*
|
|
||||||
* GUI_WINDOW_FILE_DIALOG IMPLEMENTATION
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
#if defined(GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION)
|
|
||||||
|
|
||||||
#include "raygui.h"
|
|
||||||
|
|
||||||
#include <string.h> // Required for: strcpy()
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#define MAX_DIRECTORY_FILES 2048
|
|
||||||
#define MAX_ICON_PATH_LENGTH 512
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define PATH_SEPERATOR "\\"
|
|
||||||
#else
|
|
||||||
#define PATH_SEPERATOR "/"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
|
||||||
// Detailed file info type
|
|
||||||
typedef struct FileInfo {
|
|
||||||
const char *name;
|
|
||||||
int size;
|
|
||||||
int modTime;
|
|
||||||
int type;
|
|
||||||
int icon;
|
|
||||||
} FileInfo;
|
|
||||||
#else
|
|
||||||
// Filename only
|
|
||||||
typedef char *FileInfo; // Files are just a path string
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
FileInfo *dirFilesIcon = NULL; // Path string + icon (for fancy drawing)
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Internal Module Functions Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Read files in new path
|
|
||||||
static void ReloadDirectoryFiles(GuiWindowFileDialogState *state);
|
|
||||||
|
|
||||||
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
|
||||||
// List View control for files info with extended parameters
|
|
||||||
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count,
|
|
||||||
int *focus, int *scrollIndex, int active);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath) {
|
|
||||||
GuiWindowFileDialogState state = {0};
|
|
||||||
|
|
||||||
// Init window data
|
|
||||||
state.windowBounds = (Rectangle){GetScreenWidth() / 2 - 440 / 2,
|
|
||||||
GetScreenHeight() / 2 - 310 / 2, 440, 310};
|
|
||||||
state.windowActive = false;
|
|
||||||
state.supportDrag = true;
|
|
||||||
state.dragMode = false;
|
|
||||||
state.panOffset = (Vector2){0, 0};
|
|
||||||
|
|
||||||
// Init path data
|
|
||||||
state.dirPathEditMode = false;
|
|
||||||
state.filesListActive = -1;
|
|
||||||
state.prevFilesListActive = state.filesListActive;
|
|
||||||
state.filesListScrollIndex = 0;
|
|
||||||
|
|
||||||
state.fileNameEditMode = false;
|
|
||||||
|
|
||||||
state.SelectFilePressed = false;
|
|
||||||
state.CancelFilePressed = false;
|
|
||||||
|
|
||||||
state.fileTypeActive = 0;
|
|
||||||
|
|
||||||
strcpy(state.fileNameText, "\0");
|
|
||||||
|
|
||||||
// Custom variables initialization
|
|
||||||
if (initPath && DirectoryExists(initPath)) {
|
|
||||||
strcpy(state.dirPathText, initPath);
|
|
||||||
} else if (initPath && FileExists(initPath)) {
|
|
||||||
strcpy(state.dirPathText, GetDirectoryPath(initPath));
|
|
||||||
strcpy(state.fileNameText, GetFileName(initPath));
|
|
||||||
} else
|
|
||||||
strcpy(state.dirPathText, GetWorkingDirectory());
|
|
||||||
|
|
||||||
// TODO: Why we keep a copy?
|
|
||||||
strcpy(state.dirPathTextCopy, state.dirPathText);
|
|
||||||
strcpy(state.fileNameTextCopy, state.fileNameText);
|
|
||||||
|
|
||||||
state.filterExt[0] = '\0';
|
|
||||||
// strcpy(state.filterExt, "all");
|
|
||||||
|
|
||||||
state.dirFiles.count = 0;
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update and draw file dialog
|
|
||||||
void GuiWindowFileDialog(GuiWindowFileDialogState *state) {
|
|
||||||
if (state->windowActive) {
|
|
||||||
// Update window dragging
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
if (state->supportDrag) {
|
|
||||||
Vector2 mousePosition = GetMousePosition();
|
|
||||||
|
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
|
||||||
// Window can be dragged from the top window bar
|
|
||||||
if (CheckCollisionPointRec(
|
|
||||||
mousePosition,
|
|
||||||
(Rectangle){state->windowBounds.x, state->windowBounds.y,
|
|
||||||
(float)state->windowBounds.width,
|
|
||||||
RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT})) {
|
|
||||||
state->dragMode = true;
|
|
||||||
state->panOffset.x = mousePosition.x - state->windowBounds.x;
|
|
||||||
state->panOffset.y = mousePosition.y - state->windowBounds.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->dragMode) {
|
|
||||||
state->windowBounds.x = (mousePosition.x - state->panOffset.x);
|
|
||||||
state->windowBounds.y = (mousePosition.y - state->panOffset.y);
|
|
||||||
|
|
||||||
// Check screen limits to avoid moving out of screen
|
|
||||||
if (state->windowBounds.x < 0)
|
|
||||||
state->windowBounds.x = 0;
|
|
||||||
else if (state->windowBounds.x >
|
|
||||||
(GetScreenWidth() - state->windowBounds.width))
|
|
||||||
state->windowBounds.x = GetScreenWidth() - state->windowBounds.width;
|
|
||||||
|
|
||||||
if (state->windowBounds.y < 0)
|
|
||||||
state->windowBounds.y = 0;
|
|
||||||
else if (state->windowBounds.y >
|
|
||||||
(GetScreenHeight() - state->windowBounds.height))
|
|
||||||
state->windowBounds.y =
|
|
||||||
GetScreenHeight() - state->windowBounds.height;
|
|
||||||
|
|
||||||
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
|
|
||||||
state->dragMode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Load dirFilesIcon and state->dirFiles lazily on windows open
|
|
||||||
// NOTE: They are automatically unloaded at fileDialog closing
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
if (dirFilesIcon == NULL) {
|
|
||||||
dirFilesIcon = (FileInfo *)RL_CALLOC(
|
|
||||||
MAX_DIRECTORY_FILES, sizeof(FileInfo)); // Max files to read
|
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++)
|
|
||||||
dirFilesIcon[i] =
|
|
||||||
(char *)RL_CALLOC(MAX_ICON_PATH_LENGTH, 1); // Max file name length
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load current directory files
|
|
||||||
if (state->dirFiles.paths == NULL)
|
|
||||||
ReloadDirectoryFiles(state);
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Draw window and controls
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
state->windowActive =
|
|
||||||
!GuiWindowBox(state->windowBounds, "#198# Select File Dialog");
|
|
||||||
|
|
||||||
// Draw previous directory button + logic
|
|
||||||
if (GuiButton(
|
|
||||||
(Rectangle){state->windowBounds.x + state->windowBounds.width - 48,
|
|
||||||
state->windowBounds.y + 24 + 12, 40, 24},
|
|
||||||
"< ..")) {
|
|
||||||
// Move dir path one level up
|
|
||||||
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
|
||||||
|
|
||||||
// Reload directory files (frees previous list)
|
|
||||||
ReloadDirectoryFiles(state);
|
|
||||||
|
|
||||||
state->filesListActive = -1;
|
|
||||||
memset(state->fileNameText, 0, 1024);
|
|
||||||
memset(state->fileNameTextCopy, 0, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw current directory text box info + path editing logic
|
|
||||||
if (GuiTextBox((Rectangle){state->windowBounds.x + 8,
|
|
||||||
state->windowBounds.y + 24 + 12,
|
|
||||||
state->windowBounds.width - 48 - 16, 24},
|
|
||||||
state->dirPathText, 1024, state->dirPathEditMode)) {
|
|
||||||
if (state->dirPathEditMode) {
|
|
||||||
// Verify if a valid path has been introduced
|
|
||||||
if (DirectoryExists(state->dirPathText)) {
|
|
||||||
// Reload directory files (frees previous list)
|
|
||||||
ReloadDirectoryFiles(state);
|
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
|
||||||
} else
|
|
||||||
strcpy(state->dirPathText, state->dirPathTextCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
state->dirPathEditMode = !state->dirPathEditMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// List view elements are aligned left
|
|
||||||
int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
|
|
||||||
int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
|
|
||||||
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
|
||||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
|
|
||||||
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
|
||||||
state->filesListActive = GuiListViewFiles(
|
|
||||||
(Rectangle){state->position.x + 8, state->position.y + 48 + 20,
|
|
||||||
state->windowBounds.width - 16,
|
|
||||||
state->windowBounds.height - 60 - 16 - 68},
|
|
||||||
fileInfo, state->dirFiles.count, &state->itemFocused,
|
|
||||||
&state->filesListScrollIndex, state->filesListActive);
|
|
||||||
#else
|
|
||||||
GuiListViewEx((Rectangle){state->windowBounds.x + 8,
|
|
||||||
state->windowBounds.y + 48 + 20,
|
|
||||||
state->windowBounds.width - 16,
|
|
||||||
state->windowBounds.height - 60 - 16 - 68},
|
|
||||||
(const char **)dirFilesIcon, state->dirFiles.count,
|
|
||||||
&state->filesListScrollIndex, &state->filesListActive,
|
|
||||||
&state->itemFocused);
|
|
||||||
#endif
|
|
||||||
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
|
|
||||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
|
|
||||||
|
|
||||||
// Check if a path has been selected, if it is a directory, move to that
|
|
||||||
// directory (and reload paths)
|
|
||||||
if ((state->filesListActive >= 0) &&
|
|
||||||
(state->filesListActive != state->prevFilesListActive))
|
|
||||||
//&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) ||
|
|
||||||
// IsKeyPressed(KEY_DPAD_A)))
|
|
||||||
{
|
|
||||||
strcpy(state->fileNameText,
|
|
||||||
GetFileName(state->dirFiles.paths[state->filesListActive]));
|
|
||||||
|
|
||||||
if (DirectoryExists(
|
|
||||||
TextFormat("%s/%s", state->dirPathText, state->fileNameText))) {
|
|
||||||
if (TextIsEqual(state->fileNameText, ".."))
|
|
||||||
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
|
||||||
else
|
|
||||||
strcpy(state->dirPathText,
|
|
||||||
TextFormat("%s/%s",
|
|
||||||
(strcmp(state->dirPathText, "/") == 0)
|
|
||||||
? ""
|
|
||||||
: state->dirPathText,
|
|
||||||
state->fileNameText));
|
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
|
||||||
|
|
||||||
// Reload directory files (frees previous list)
|
|
||||||
ReloadDirectoryFiles(state);
|
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
|
||||||
|
|
||||||
state->filesListActive = -1;
|
|
||||||
strcpy(state->fileNameText, "\0");
|
|
||||||
strcpy(state->fileNameTextCopy, state->fileNameText);
|
|
||||||
}
|
|
||||||
|
|
||||||
state->prevFilesListActive = state->filesListActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw bottom controls
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
GuiLabel(
|
|
||||||
(Rectangle){state->windowBounds.x + 8,
|
|
||||||
state->windowBounds.y + state->windowBounds.height - 68, 60,
|
|
||||||
24},
|
|
||||||
"File name:");
|
|
||||||
if (GuiTextBox(
|
|
||||||
(Rectangle){state->windowBounds.x + 72,
|
|
||||||
state->windowBounds.y + state->windowBounds.height - 68,
|
|
||||||
state->windowBounds.width - 184, 24},
|
|
||||||
state->fileNameText, 128, state->fileNameEditMode)) {
|
|
||||||
if (*state->fileNameText) {
|
|
||||||
// Verify if a valid filename has been introduced
|
|
||||||
if (FileExists(
|
|
||||||
TextFormat("%s/%s", state->dirPathText, state->fileNameText))) {
|
|
||||||
// Select filename from list view
|
|
||||||
for (int i = 0; i < state->dirFiles.count; i++) {
|
|
||||||
if (TextIsEqual(state->fileNameText, state->dirFiles.paths[i])) {
|
|
||||||
state->filesListActive = i;
|
|
||||||
strcpy(state->fileNameTextCopy, state->fileNameText);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!state->saveFileMode) {
|
|
||||||
strcpy(state->fileNameText, state->fileNameTextCopy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state->fileNameEditMode = !state->fileNameEditMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){state->windowBounds.x + 8,
|
|
||||||
state->windowBounds.y + state->windowBounds.height -
|
|
||||||
24 - 12,
|
|
||||||
68, 24},
|
|
||||||
"File filter:");
|
|
||||||
GuiComboBox((Rectangle){state->windowBounds.x + 72,
|
|
||||||
state->windowBounds.y + state->windowBounds.height -
|
|
||||||
24 - 12,
|
|
||||||
state->windowBounds.width - 184, 24},
|
|
||||||
"All files", &state->fileTypeActive);
|
|
||||||
|
|
||||||
state->SelectFilePressed = GuiButton(
|
|
||||||
(Rectangle){state->windowBounds.x + state->windowBounds.width - 96 - 8,
|
|
||||||
state->windowBounds.y + state->windowBounds.height - 68, 96,
|
|
||||||
24},
|
|
||||||
"Select");
|
|
||||||
|
|
||||||
if (GuiButton(
|
|
||||||
(Rectangle){
|
|
||||||
state->windowBounds.x + state->windowBounds.width - 96 - 8,
|
|
||||||
state->windowBounds.y + state->windowBounds.height - 24 - 12,
|
|
||||||
96, 24},
|
|
||||||
"Cancel"))
|
|
||||||
state->windowActive = false;
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Exit on file selected
|
|
||||||
if (state->SelectFilePressed)
|
|
||||||
state->windowActive = false;
|
|
||||||
|
|
||||||
// File dialog has been closed, free all memory before exit
|
|
||||||
if (!state->windowActive) {
|
|
||||||
// Free dirFilesIcon memory
|
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++)
|
|
||||||
RL_FREE(dirFilesIcon[i]);
|
|
||||||
|
|
||||||
RL_FREE(dirFilesIcon);
|
|
||||||
dirFilesIcon = NULL;
|
|
||||||
|
|
||||||
// Unload directory file paths
|
|
||||||
UnloadDirectoryFiles(state->dirFiles);
|
|
||||||
|
|
||||||
// Reset state variables
|
|
||||||
state->dirFiles.count = 0;
|
|
||||||
state->dirFiles.capacity = 0;
|
|
||||||
state->dirFiles.paths = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare two files from a directory
|
|
||||||
static inline int FileCompare(const char *d1, const char *d2, const char *dir) {
|
|
||||||
const bool b1 = DirectoryExists(TextFormat("%s/%s", dir, d1));
|
|
||||||
const bool b2 = DirectoryExists(TextFormat("%s/%s", dir, d2));
|
|
||||||
|
|
||||||
if (b1 && !b2)
|
|
||||||
return -1;
|
|
||||||
if (!b1 && b2)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!FileExists(TextFormat("%s/%s", dir, d1)))
|
|
||||||
return 1;
|
|
||||||
if (!FileExists(TextFormat("%s/%s", dir, d2)))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return strcmp(d1, d2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read files in new path
|
|
||||||
static void ReloadDirectoryFiles(GuiWindowFileDialogState *state) {
|
|
||||||
UnloadDirectoryFiles(state->dirFiles);
|
|
||||||
|
|
||||||
state->dirFiles = LoadDirectoryFilesEx(
|
|
||||||
state->dirPathText,
|
|
||||||
(state->filterExt[0] == '\0') ? NULL : state->filterExt, false);
|
|
||||||
state->itemFocused = 0;
|
|
||||||
|
|
||||||
// Reset dirFilesIcon memory
|
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++)
|
|
||||||
memset(dirFilesIcon[i], 0, MAX_ICON_PATH_LENGTH);
|
|
||||||
|
|
||||||
// Copy paths as icon + fileNames into dirFilesIcon
|
|
||||||
for (int i = 0; i < state->dirFiles.count; i++) {
|
|
||||||
if (IsPathFile(state->dirFiles.paths[i])) {
|
|
||||||
// Path is a file, a file icon for convenience (for some recognized
|
|
||||||
// extensions)
|
|
||||||
if (IsFileExtension(state->dirFiles.paths[i],
|
|
||||||
".png;.bmp;.tga;.gif;.jpg;.jpeg;.psd;.hdr;.qoi;.dds;."
|
|
||||||
"pkm;.ktx;.pvr;.astc")) {
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#12#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
} else if (IsFileExtension(
|
|
||||||
state->dirFiles.paths[i],
|
|
||||||
".wav;.mp3;.ogg;.flac;.xm;.mod;.it;.wma;.aiff")) {
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#11#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
} else if (IsFileExtension(state->dirFiles.paths[i],
|
|
||||||
".txt;.info;.md;.nfo;.xml;.json;.c;.cpp;.cs;."
|
|
||||||
"lua;.py;.glsl;.vs;.fs")) {
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#10#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
} else if (IsFileExtension(state->dirFiles.paths[i],
|
|
||||||
".exe;.bin;.raw;.msi")) {
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#200#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
} else
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#218#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
} else {
|
|
||||||
// Path is a directory, add a directory icon
|
|
||||||
strcpy(dirFilesIcon[i],
|
|
||||||
TextFormat("#1#%s", GetFileName(state->dirFiles.paths[i])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
|
||||||
// List View control for files info with extended parameters
|
|
||||||
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count,
|
|
||||||
int *focus, int *scrollIndex, int *active) {
|
|
||||||
int result = 0;
|
|
||||||
GuiState state = guiState;
|
|
||||||
int itemFocused = (focus == NULL) ? -1 : *focus;
|
|
||||||
int itemSelected = *active;
|
|
||||||
|
|
||||||
// Check if we need a scroll bar
|
|
||||||
bool useScrollBar = false;
|
|
||||||
if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) +
|
|
||||||
GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING)) *
|
|
||||||
count >
|
|
||||||
bounds.height)
|
|
||||||
useScrollBar = true;
|
|
||||||
|
|
||||||
// Define base item rectangle [0]
|
|
||||||
Rectangle itemBounds = {0};
|
|
||||||
itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING);
|
|
||||||
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) +
|
|
||||||
GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
|
||||||
itemBounds.width = bounds.width -
|
|
||||||
2 * GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) -
|
|
||||||
GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
|
||||||
itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
|
|
||||||
if (useScrollBar)
|
|
||||||
itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
|
|
||||||
|
|
||||||
// Get items on the list
|
|
||||||
int visibleItems =
|
|
||||||
bounds.height / (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) +
|
|
||||||
GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
|
||||||
if (visibleItems > count)
|
|
||||||
visibleItems = count;
|
|
||||||
|
|
||||||
int startIndex = (scrollIndex == NULL) ? 0 : *scrollIndex;
|
|
||||||
if ((startIndex < 0) || (startIndex > (count - visibleItems)))
|
|
||||||
startIndex = 0;
|
|
||||||
int endIndex = startIndex + visibleItems;
|
|
||||||
|
|
||||||
// Update control
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
if ((state != GUI_STATE_DISABLED) && !guiLocked) {
|
|
||||||
Vector2 mousePoint = GetMousePosition();
|
|
||||||
|
|
||||||
// Check mouse inside list view
|
|
||||||
if (CheckCollisionPointRec(mousePoint, bounds)) {
|
|
||||||
state = GUI_STATE_FOCUSED;
|
|
||||||
|
|
||||||
// Check focused and selected item
|
|
||||||
for (int i = 0; i < visibleItems; i++) {
|
|
||||||
if (CheckCollisionPointRec(mousePoint, itemBounds)) {
|
|
||||||
itemFocused = startIndex + i;
|
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
|
||||||
itemSelected = startIndex + i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update item rectangle y position for next item
|
|
||||||
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) +
|
|
||||||
GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useScrollBar) {
|
|
||||||
int wheelMove = GetMouseWheelMove();
|
|
||||||
startIndex -= wheelMove;
|
|
||||||
|
|
||||||
if (startIndex < 0)
|
|
||||||
startIndex = 0;
|
|
||||||
else if (startIndex > (count - visibleItems))
|
|
||||||
startIndex = count - visibleItems;
|
|
||||||
|
|
||||||
endIndex = startIndex + visibleItems;
|
|
||||||
if (endIndex > count)
|
|
||||||
endIndex = count;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
itemFocused = -1;
|
|
||||||
|
|
||||||
// Reset item rectangle y to [0]
|
|
||||||
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) +
|
|
||||||
GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Draw control
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
DrawRectangleRec(bounds, GetColor(GuiGetStyle(
|
|
||||||
DEFAULT, BACKGROUND_COLOR))); // Draw background
|
|
||||||
DrawRectangleLinesEx(
|
|
||||||
bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state * 3)), guiAlpha));
|
|
||||||
|
|
||||||
// TODO: Draw list view header with file sections: icon+name | size | type |
|
|
||||||
// modTime
|
|
||||||
|
|
||||||
// Draw visible items
|
|
||||||
for (int i = 0; i < visibleItems; i++) {
|
|
||||||
if (state == GUI_STATE_DISABLED) {
|
|
||||||
if ((startIndex + i) == itemSelected) {
|
|
||||||
DrawRectangleRec(
|
|
||||||
itemBounds,
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)),
|
|
||||||
guiAlpha));
|
|
||||||
DrawRectangleLinesEx(
|
|
||||||
itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)),
|
|
||||||
guiAlpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Draw full file info line: icon+name | size | type | modTime
|
|
||||||
|
|
||||||
GuiDrawText(
|
|
||||||
files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds),
|
|
||||||
GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
|
|
||||||
} else {
|
|
||||||
if ((startIndex + i) == itemSelected) {
|
|
||||||
// Draw item selected
|
|
||||||
DrawRectangleRec(
|
|
||||||
itemBounds,
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)),
|
|
||||||
guiAlpha));
|
|
||||||
DrawRectangleLinesEx(
|
|
||||||
itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)),
|
|
||||||
guiAlpha));
|
|
||||||
|
|
||||||
GuiDrawText(files[startIndex + i].name,
|
|
||||||
GetTextBounds(DEFAULT, itemBounds),
|
|
||||||
GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)),
|
|
||||||
guiAlpha));
|
|
||||||
} else if ((startIndex + i) == itemFocused) {
|
|
||||||
// Draw item focused
|
|
||||||
DrawRectangleRec(
|
|
||||||
itemBounds,
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)),
|
|
||||||
guiAlpha));
|
|
||||||
DrawRectangleLinesEx(
|
|
||||||
itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)),
|
|
||||||
guiAlpha));
|
|
||||||
|
|
||||||
GuiDrawText(files[startIndex + i].name,
|
|
||||||
GetTextBounds(DEFAULT, itemBounds),
|
|
||||||
GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)),
|
|
||||||
guiAlpha));
|
|
||||||
} else {
|
|
||||||
// Draw item normal
|
|
||||||
GuiDrawText(
|
|
||||||
files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds),
|
|
||||||
GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT),
|
|
||||||
Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update item rectangle y position for next item
|
|
||||||
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) +
|
|
||||||
GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useScrollBar) {
|
|
||||||
Rectangle scrollBarBounds = {
|
|
||||||
bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) -
|
|
||||||
GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
|
||||||
bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH),
|
|
||||||
(float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
|
||||||
bounds.height - 2 * GuiGetStyle(DEFAULT, BORDER_WIDTH)};
|
|
||||||
|
|
||||||
// Calculate percentage of visible items and apply same percentage to
|
|
||||||
// scrollbar
|
|
||||||
float percentVisible = (float)(endIndex - startIndex) / count;
|
|
||||||
float sliderSize = bounds.height * percentVisible;
|
|
||||||
|
|
||||||
int prevSliderSize =
|
|
||||||
GuiGetStyle(SCROLLBAR, SLIDER_WIDTH); // Save default slider size
|
|
||||||
int prevScrollSpeed =
|
|
||||||
GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
|
|
||||||
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, sliderSize); // Change slider size
|
|
||||||
GuiSetStyle(SCROLLBAR, SCROLL_SPEED,
|
|
||||||
count - visibleItems); // Change scroll speed
|
|
||||||
|
|
||||||
startIndex =
|
|
||||||
GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
|
|
||||||
|
|
||||||
GuiSetStyle(SCROLLBAR, SCROLL_SPEED,
|
|
||||||
prevScrollSpeed); // Reset scroll speed to default
|
|
||||||
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH,
|
|
||||||
prevSliderSize); // Reset slider size to default
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
|
|
||||||
if (focus != NULL)
|
|
||||||
*focus = itemFocused;
|
|
||||||
if (scrollIndex != NULL)
|
|
||||||
*scrollIndex = startIndex;
|
|
||||||
|
|
||||||
*active = itemSelected;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif // USE_CUSTOM_LISTVIEW_FILEINFO
|
|
||||||
|
|
||||||
#endif // GUI_FILE_DIALOG_IMPLEMENTATION
|
|
1
3rd-party/raygui
vendored
Submodule
1
3rd-party/raygui
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 499e8bf7b1d9b0a92af8f685e646bc61f13c6dff
|
2
3rd-party/raygui.c
vendored
2
3rd-party/raygui.c
vendored
|
@ -3,4 +3,4 @@
|
||||||
#undef RAYGUI_IMPLEMENTATION
|
#undef RAYGUI_IMPLEMENTATION
|
||||||
|
|
||||||
#define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
|
#define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
|
||||||
#include "gui_window_file_dialog.h"
|
#include "../examples/custom_file_dialog/gui_window_file_dialog.h"
|
||||||
|
|
5527
3rd-party/raygui.h
vendored
5527
3rd-party/raygui.h
vendored
File diff suppressed because it is too large
Load diff
1
3rd-party/raylib
vendored
Submodule
1
3rd-party/raylib
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 18bedbd0952c27b0eb8bc5df0df4acf589cef181
|
0
Tupfile.ini
Normal file
0
Tupfile.ini
Normal file
31
build.zig
31
build.zig
|
@ -14,22 +14,23 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
// We cannot directly use modules since v4.5 is not compatible with zig
|
//
|
||||||
// v0.11
|
// C dependencies
|
||||||
const raylib_dep = b.dependency("raylib", .{
|
//
|
||||||
.target = target,
|
exe.linkLibC();
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
exe.linkLibrary(raylib_dep.artifact("raylib"));
|
|
||||||
|
|
||||||
const cflags = [_][]const u8{};
|
// Raylib
|
||||||
exe.addCSourceFile(.{
|
exe.addIncludePath(.{ .path = "build/raylib/include" });
|
||||||
.file = .{
|
exe.addLibraryPath(.{ .path = "build/raylib" });
|
||||||
.path = "3rd-party/raygui.c",
|
exe.linkSystemLibrary("raylib");
|
||||||
},
|
|
||||||
.flags = &cflags,
|
// Raygui
|
||||||
});
|
exe.addIncludePath(.{ .path = "3rd-party/raygui/src" });
|
||||||
exe.addIncludePath(.{ .path = "3rd-party/" });
|
exe.addIncludePath(.{ .path = "3rd-party/raygui" });
|
||||||
|
exe.addLibraryPath(.{ .path = "build/raygui" });
|
||||||
|
exe.linkSystemLibrary("raygui");
|
||||||
|
|
||||||
|
// SQLite
|
||||||
exe.linkSystemLibrary("sqlite3");
|
exe.linkSystemLibrary("sqlite3");
|
||||||
|
|
||||||
// This declares intent for the executable to be installed into the
|
// This declares intent for the executable to be installed into the
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
.{
|
|
||||||
.name = "fabapp",
|
|
||||||
.version = "0.1.0",
|
|
||||||
.dependencies = .{
|
|
||||||
.raylib = .{
|
|
||||||
.url = "https://github.com/raysan5/raylib/archive/bc15c19518968878b68bbfe8eac3fe4297f11770.tar.gz",
|
|
||||||
.hash = "122093954b8c911e507de32d83a2046e122c6aca64e71f5244d54f9bbb93730c3ab7",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
70
flake.lock
70
flake.lock
|
@ -1,21 +1,5 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1673956053,
|
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
@ -34,21 +18,6 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1659877975,
|
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1696983906,
|
"lastModified": 1696983906,
|
||||||
|
@ -99,48 +68,11 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689088367,
|
|
||||||
"narHash": "sha256-Y2tl2TlKCWEHrOeM9ivjCLlRAKH3qoPUE/emhZECU14=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "5c9ddb86679c400d6b7360797b8a22167c2053f8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "release-23.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||||
"zig-overlay": "zig-overlay"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zig-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1697198920,
|
|
||||||
"narHash": "sha256-dtaoksNoOMC3H+FDF3cK+bP+jYvJokYBAFvzCALLDYk=",
|
|
||||||
"owner": "mitchellh",
|
|
||||||
"repo": "zig-overlay",
|
|
||||||
"rev": "2d779a7657e346323ab048b218994dbdc42655d7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "mitchellh",
|
|
||||||
"repo": "zig-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
44
flake.nix
44
flake.nix
|
@ -4,27 +4,24 @@
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
|
||||||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
zig-overlay.url = "github:mitchellh/zig-overlay";
|
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ flake-parts, nixpkgs, ... }:
|
outputs = inputs@{ flake-parts, nixpkgs, ... }:
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
flake = {
|
flake = { };
|
||||||
# Put your original flake attributes here.
|
|
||||||
};
|
|
||||||
|
|
||||||
systems = [ "x86_64-linux" ];
|
systems = [ "x86_64-linux" ];
|
||||||
|
|
||||||
# https://flake.parts/module-arguments.html#persystem-module-parameters
|
# https://flake.parts/module-arguments.html#persystem-module-parameters
|
||||||
perSystem = { pkgs, system, ... }: {
|
perSystem = { pkgs, system, ... }: {
|
||||||
# We need unstable for Zig
|
|
||||||
_module.args.pkgs = import inputs.nixpkgs-unstable {
|
_module.args.pkgs = import inputs.nixpkgs-unstable {
|
||||||
inherit system;
|
inherit system;
|
||||||
# https://flake.parts/overlays
|
# https://flake.parts/overlays
|
||||||
overlays = [
|
# NOTE: zig overlay triggers issues with X11/GL libraries
|
||||||
inputs.zig-overlay.overlays.default
|
# This might be misconfiguration on my end
|
||||||
];
|
overlays = [ ];
|
||||||
config = { };
|
config = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,24 +29,41 @@
|
||||||
|
|
||||||
devShells.default = with pkgs;
|
devShells.default = with pkgs;
|
||||||
mkShell {
|
mkShell {
|
||||||
|
# EM_CONFIG = pkgs.writeText ".emscripten" ''
|
||||||
|
# EMSCRIPTEN_ROOT = '${pkgs.emscripten}/share/emscripten'
|
||||||
|
# LLVM_ROOT = '${pkgs.emscripten.llvmEnv}/bin'
|
||||||
|
# BINARYEN_ROOT = '${pkgs.binaryen}'
|
||||||
|
# NODE_JS = '${pkgs.nodejs-18_x}/bin/node'
|
||||||
|
# CACHE = '${toString ./.cache}'
|
||||||
|
# '';
|
||||||
|
|
||||||
|
nativeBuildInputs = [ clang cmake just ninja tup ];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
sqlite
|
sqlite
|
||||||
|
|
||||||
# Zig / webAssembly impl.
|
# Zig / webAssembly impl.
|
||||||
zig
|
zig
|
||||||
# zigpkgs."master" # Issue with X11/GL libraries
|
|
||||||
zls
|
zls
|
||||||
emscripten
|
emscripten
|
||||||
|
|
||||||
# Linux graphical deps
|
# Linux graphical deps
|
||||||
|
## X11
|
||||||
xorg.libX11
|
xorg.libX11
|
||||||
|
xorg.libXcursor
|
||||||
|
xorg.libXi
|
||||||
|
xorg.libXext
|
||||||
|
xorg.libXrandr
|
||||||
|
xorg.libXinerama
|
||||||
|
xorg.libxcb
|
||||||
libGL
|
libGL
|
||||||
# xorg.libXcursor
|
libGLU
|
||||||
# xorg.libXi
|
pkg-config
|
||||||
# xorg.libXext
|
|
||||||
# xorg.libXrandr
|
## Wayland
|
||||||
# xorg.libXinerama
|
wayland-protocols
|
||||||
# libGLU
|
wayland
|
||||||
|
libxkbcommon
|
||||||
];
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
39
justfile
39
justfile
|
@ -1,16 +1,35 @@
|
||||||
|
cpp_build_dir := justfile_directory() / "build"
|
||||||
|
|
||||||
alias b := build
|
alias b := build
|
||||||
alias r := run
|
alias r := run
|
||||||
alias t := test
|
alias t := test
|
||||||
alias fmt := format
|
alias fmt := format
|
||||||
|
|
||||||
|
pre-build:
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
raylib:
|
||||||
|
mkdir -p {{ cpp_build_dir }}
|
||||||
|
cmake -B {{ cpp_build_dir }} -S {{ justfile_directory() }}/3rd-party/raylib \
|
||||||
|
-DBUILD_EXAMPLES=OFF
|
||||||
|
cmake --build {{ cpp_build_dir }}
|
||||||
|
|
||||||
|
raygui:
|
||||||
|
tup
|
||||||
|
|
||||||
|
deps: pre-build raylib raygui
|
||||||
|
|
||||||
build:
|
build:
|
||||||
zig build
|
zig build -Doptimize=Debug
|
||||||
|
# zig build -Doptimize=Debug -Dtarget=x86_64-linux-gnu.2.30
|
||||||
|
# zig build -Doptimize=Debug -Dtarget=native-native-musl #--search-prefix /nix/store/n12a68qch9s85k6ni4m4r4xxr8lwys1i-sqlite-3.41.2/lib
|
||||||
|
|
||||||
web-build:
|
web-build: pre-build
|
||||||
# zig build-lib src/main.zig -target wasm32-freestanding -dynamic -rdynamic
|
# zig build-lib src/main.zig -target wasm32-freestanding -dynamic -rdynamic
|
||||||
zig build -Dtarget=wasm32-emscripten --sysroot /nix/store/zll7a6ns3avx509kgx0jjghz8g89l2g0-emscripten-3.1.45
|
zig build -Dtarget=wasm32-emscripten --sysroot /nix/store/lszbak7w3k1jmx3cm3qb2qzillsib71v-emscripten-3.1.24/bin/emcc
|
||||||
|
# zig build -Dtarget=wasm32-emscripten
|
||||||
|
|
||||||
run: build
|
run:
|
||||||
nixGL zig build run
|
nixGL zig build run
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
@ -20,7 +39,11 @@ format:
|
||||||
fd -e zig -X zig fmt {}
|
fd -e zig -X zig fmt {}
|
||||||
fd -e nix -X nix fmt {}
|
fd -e nix -X nix fmt {}
|
||||||
|
|
||||||
update-deps:
|
# update-deps:
|
||||||
# We cannot easily add header-only C library with package manager
|
# # We cannot easily add header-only C library with package manager
|
||||||
curl https://raw.githubusercontent.com/raysan5/raygui/master/src/raygui.h --remote-name --output-dir 3rd-party/
|
# curl https://raw.githubusercontent.com/raysan5/raygui/master/src/raygui.h --remote-name --output-dir 3rd-party/
|
||||||
curl https://raw.githubusercontent.com/raysan5/raygui/master/examples/custom_file_dialog/gui_window_file_dialog.h --remote-name --output-dir 3rd-party/
|
# curl https://raw.githubusercontent.com/raysan5/raygui/master/examples/custom_file_dialog/gui_window_file_dialog.h --remote-name --output-dir 3rd-party/
|
||||||
|
|
||||||
|
envrc:
|
||||||
|
echo "use flake ."
|
||||||
|
echo "export CMAKE_GENERATOR=Ninja"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub usingnamespace @cImport({
|
pub usingnamespace @cImport({
|
||||||
@cInclude("raylib.h");
|
@cInclude("raylib.h");
|
||||||
@cInclude("raygui.h");
|
@cInclude("raygui.h");
|
||||||
@cInclude("gui_window_file_dialog.h");
|
@cInclude("examples/custom_file_dialog/gui_window_file_dialog.h");
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue