summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.c61
-rw-r--r--src/lua_core.c233
-rw-r--r--src/main.c114
-rw-r--r--src/splash.c198
-rw-r--r--src/state.c77
5 files changed, 641 insertions, 42 deletions
diff --git a/src/core.c b/src/core.c
index 338778e..0238432 100644
--- a/src/core.c
+++ b/src/core.c
@@ -4,6 +4,14 @@
#include "textures.h"
#include "lua_core.h"
+/* Forward declarations from lua_core.c for asset loading */
+extern int g_totalAssets;
+extern int g_loadedAssets;
+extern char g_currentAssetName[256];
+extern bool g_showLoadingScreen;
+extern float g_loadingProgress;
+extern void drawLoadingScreen();
+
static size_t getBufferElementSize( Buffer* buffer ) {
switch ( buffer->type ) {
case BUFFER_UNSIGNED_CHAR: return sizeof( unsigned char );
@@ -1956,6 +1964,59 @@ int lcoreGetApplicationDirectory( lua_State* L ) {
}
/*
+> RL.BeginAssetLoading( int totalAssets )
+
+Initialize asset loading progress tracking
+
+- totalAssets: Total number of assets to load
+*/
+int lcoreBeginAssetLoading( lua_State* L ) {
+ g_totalAssets = luaL_checkinteger( L, 1 );
+ g_loadedAssets = 0;
+ g_showLoadingScreen = true;
+ g_loadingProgress = 0.0f;
+ g_currentAssetName[0] = '\0';
+
+ return 0;
+}
+
+/*
+> RL.UpdateAssetLoading( string assetName )
+
+Update loading progress for current asset
+
+- assetName: Name of the asset currently being loaded
+*/
+int lcoreUpdateAssetLoading( lua_State* L ) {
+ const char* assetName = luaL_checkstring( L, 1 );
+ strncpy( g_currentAssetName, assetName, sizeof(g_currentAssetName) - 1 );
+ g_currentAssetName[sizeof(g_currentAssetName) - 1] = '\0';
+
+ g_loadedAssets++;
+ g_loadingProgress = (float)g_loadedAssets / (float)g_totalAssets;
+
+ if ( g_showLoadingScreen ) {
+ drawLoadingScreen();
+ }
+
+ return 0;
+}
+
+/*
+> RL.EndAssetLoading()
+
+Finish asset loading and hide loading screen
+*/
+int lcoreEndAssetLoading( lua_State* L ) {
+ g_showLoadingScreen = false;
+ g_totalAssets = 0;
+ g_loadedAssets = 0;
+ g_currentAssetName[0] = '\0';
+
+ return 0;
+}
+
+/*
> success = RL.MakeDirectory( string dirPath )
Create directories (including full path requested), returns 0 on success
diff --git a/src/lua_core.c b/src/lua_core.c
index c619b9c..8d4bf52 100644
--- a/src/lua_core.c
+++ b/src/lua_core.c
@@ -15,6 +15,21 @@
#include "reasings.h"
#include "bitwiseOp.h"
+#ifdef EMBED_MAIN
+ #include "embedded_main.h"
+#endif
+
+#ifdef EMBED_ASSETS
+ #include "embedded_assets.h"
+#endif
+
+/* Asset loading progress tracking (non-static so core.c can access) */
+int g_totalAssets = 0;
+int g_loadedAssets = 0;
+char g_currentAssetName[256] = { '\0' };
+bool g_showLoadingScreen = false;
+float g_loadingProgress = 0.0f;
+
#ifdef PLATFORM_DESKTOP
#include "platforms/core_desktop_glfw.c"
#elif PLATFORM_DESKTOP_SDL2
@@ -25,6 +40,152 @@
#include "platforms/core_web.c"
#endif
+/* Draw a nice loading screen with progress bar (non-static so core.c can call it) */
+void drawLoadingScreen() {
+ int screenWidth = GetScreenWidth();
+ int screenHeight = GetScreenHeight();
+
+ BeginDrawing();
+ ClearBackground( BLACK );
+
+ int centerX = screenWidth / 2;
+ int centerY = screenHeight / 2;
+
+ const char* title = "LOADING";
+ int titleSize = 32;
+ int titleWidth = MeasureText( title, titleSize );
+
+ DrawText( title, centerX - titleWidth / 2, centerY - 80, titleSize, WHITE );
+
+ static float dotTime = 0.0f;
+ dotTime += 0.016f;
+ int dotCount = (int)(dotTime * 2.0f) % 4;
+
+ int dotStartX = centerX + titleWidth / 2 + 10;
+ int dotY = centerY - 80 + titleSize - 12;
+ for ( int i = 0; i < dotCount; i++ ) {
+ DrawRectangle( dotStartX + i * 8, dotY, 4, 4, WHITE );
+ }
+
+ int barWidth = 200;
+ int barHeight = 16;
+ int barX = centerX - barWidth / 2;
+ int barY = centerY;
+
+ DrawRectangle( barX - 2, barY - 2, barWidth + 4, barHeight + 4, WHITE );
+ DrawRectangle( barX, barY, barWidth, barHeight, BLACK );
+
+ int fillWidth = (int)(barWidth * g_loadingProgress);
+ if ( fillWidth > 0 ) {
+ DrawRectangle( barX, barY, fillWidth, barHeight, WHITE );
+
+ for ( int y = 0; y < barHeight; y += 2 ) {
+ for ( int x = 0; x < fillWidth; x += 4 ) {
+ if ( (x + y) % 4 == 0 ) {
+ DrawRectangle( barX + x, barY + y, 1, 1, BLACK );
+ }
+ }
+ }
+ }
+
+ if ( g_totalAssets > 0 ) {
+ char progressText[32];
+ sprintf( progressText, "%d/%d", g_loadedAssets, g_totalAssets );
+ int progressWidth = MeasureText( progressText, 16 );
+ DrawText( progressText, centerX - progressWidth / 2, barY + barHeight + 12, 16, WHITE );
+ }
+
+ if ( g_currentAssetName[0] != '\0' ) {
+ int assetNameWidth = MeasureText( g_currentAssetName, 10 );
+ DrawText( g_currentAssetName, centerX - assetNameWidth / 2, barY + barHeight + 36, 10, WHITE );
+ }
+
+ int cornerSize = 8;
+ int margin = 40;
+
+ DrawRectangle( margin, margin, cornerSize, 2, WHITE );
+ DrawRectangle( margin, margin, 2, cornerSize, WHITE );
+
+ DrawRectangle( screenWidth - margin - cornerSize, margin, cornerSize, 2, WHITE );
+ DrawRectangle( screenWidth - margin - 2, margin, 2, cornerSize, WHITE );
+
+ DrawRectangle( margin, screenHeight - margin - cornerSize, 2, cornerSize, WHITE );
+ DrawRectangle( margin, screenHeight - margin - 2, cornerSize, 2, WHITE );
+
+ DrawRectangle( screenWidth - margin - cornerSize, screenHeight - margin - 2, cornerSize, 2, WHITE );
+ DrawRectangle( screenWidth - margin - 2, screenHeight - margin - cornerSize, 2, cornerSize, WHITE );
+
+ EndDrawing();
+}
+
+#ifdef EMBED_MAIN
+/* Custom loader for embedded Lua files */
+static int embedded_lua_loader( lua_State* L ) {
+ const char* name = lua_tostring( L, 1 );
+ if ( name == NULL ) return 0;
+
+ for ( int i = 0; i < embedded_lua_file_count; i++ ) {
+ const EmbeddedLuaFile* file = &embedded_lua_files[i];
+
+ const char* basename = file->name;
+ size_t name_len = strlen( name );
+ size_t base_len = strlen( basename );
+
+ if ( strcmp( basename, name ) == 0 ||
+ ( base_len > 4 && strcmp( basename + base_len - 4, ".lua" ) == 0 &&
+ strncmp( basename, name, base_len - 4 ) == 0 && name_len == base_len - 4 ) ) {
+
+ if ( luaL_loadbuffer( L, (const char*)file->data, file->size, file->name ) == 0 ) {
+ return 1;
+ }
+ else {
+ lua_pushfstring( L, "\n\tembedded loader error: %s", lua_tostring( L, -1 ) );
+ return 1;
+ }
+ }
+ }
+
+ lua_pushfstring( L, "\n\tno embedded file '%s'", name );
+ return 1;
+}
+#endif
+
+#ifdef EMBED_ASSETS
+/* Helper function to find embedded asset by name */
+static const EmbeddedAsset* find_embedded_asset( const char* name ) {
+ if ( name == NULL ) return NULL;
+
+ for ( int i = 0; i < embedded_asset_count; i++ ) {
+ if ( strcmp( embedded_assets[i].name, name ) == 0 ) {
+ return &embedded_assets[i];
+ }
+ }
+ return NULL;
+}
+
+/* Override LoadFileData to check embedded assets first */
+unsigned char* LoadFileData_Embedded( const char* fileName, int* dataSize ) {
+ const EmbeddedAsset* asset = find_embedded_asset( fileName );
+ if ( asset != NULL ) {
+ *dataSize = asset->size;
+ unsigned char* data = (unsigned char*)malloc( asset->size );
+ if ( data != NULL ) {
+ memcpy( data, asset->data, asset->size );
+ }
+ return data;
+ }
+ return LoadFileData( fileName, dataSize );
+}
+
+/* Check if file exists in embedded assets */
+bool FileExists_Embedded( const char* fileName ) {
+ if ( find_embedded_asset( fileName ) != NULL ) {
+ return true;
+ }
+ return FileExists( fileName );
+}
+#endif
+
/* Custom implementation since LuaJIT doesn't have lua_geti. */
static void lua_getiCustom( lua_State* L, int index, int i ) {
lua_pushinteger( L, i ); // Push the index onto the stack
@@ -1446,11 +1607,51 @@ int luaTraceback( lua_State* L ) {
return 1;
}
-void luaCallMain() {
+bool luaCallMain() {
lua_State* L = state->luaState;
char path[ STRING_LEN ] = { '\0' };
+ /* Show loading screen */
+ BeginDrawing();
+ ClearBackground( RAYWHITE );
+ const char* loadingText = "Loading...";
+ int fontSize = 40;
+ int textWidth = MeasureText( loadingText, fontSize );
+ DrawText( loadingText, ( GetScreenWidth() - textWidth ) / 2, GetScreenHeight() / 2 - fontSize / 2, fontSize, DARKGRAY );
+ EndDrawing();
+
+#ifdef EMBED_MAIN
+ /* Register custom loader for embedded files */
+ lua_getglobal( L, "package" );
+ lua_getfield( L, -1, "loaders" );
+ if ( lua_isnil( L, -1 ) ) {
+ lua_pop( L, 1 );
+ lua_getfield( L, -1, "searchers" ); /* Lua 5.2+ uses 'searchers' */
+ }
+
+ /* Insert our loader at position 2 (before file loaders) */
+ lua_len( L, -1 );
+ int num_loaders = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ for ( int i = num_loaders; i >= 2; i-- ) {
+ lua_rawgeti( L, -1, i );
+ lua_rawseti( L, -2, i + 1 );
+ }
+ lua_pushcfunction( L, embedded_lua_loader );
+ lua_rawseti( L, -2, 2 );
+ lua_pop( L, 2 ); /* Pop loaders/searchers and package */
+
+ /* Load from embedded data */
+ if ( luaL_loadbuffer( L, (const char*)embedded_main_lua, embedded_main_lua_len, "main.lua" ) != 0 ) {
+ TraceLog( LOG_ERROR, "Lua error loading embedded main.lua: %s\n", lua_tostring( L, -1 ) );
+ return false;
+ }
+ if ( lua_pcall( L, 0, 0, 0 ) != 0 ) {
+ TraceLog( LOG_ERROR, "Lua error executing embedded main.lua: %s\n", lua_tostring( L, -1 ) );
+ return false;
+ }
+#else
/* If web, set path to resources folder. */
#ifdef PLATFORM_WEB
snprintf( path, STRING_LEN, "main.lua" );
@@ -1467,43 +1668,37 @@ void luaCallMain() {
#endif
if ( !FileExists( path ) ) {
TraceLog( LOG_ERROR, "Cannot find file: %s\n", path );
- state->run = false;
- return;
+ return false;
}
luaL_dofile( L, path );
/* Check errors in main.lua */
if ( lua_tostring( L, -1 ) ) {
TraceLog( LOG_ERROR, "Lua error: %s\n", lua_tostring( L, -1 ) );
- state->run = false;
- return;
+ return false;
}
+#endif
lua_pushcfunction( L, luaTraceback );
int tracebackidx = lua_gettop( L );
/* Apply custom callback here. */
SetTraceLogCallback( logCustom );
lua_getglobal( L, "RL" );
- lua_getfield( L, -1, "config" );
+ lua_getfield( L, -1, "init" );
if ( lua_isfunction( L, -1 ) ) {
if ( lua_pcall( L, 0, 0, tracebackidx ) != 0 ) {
TraceLog( LOG_ERROR, "Lua error: %s", lua_tostring( L, -1 ) );
- state->run = false;
- return;
+ return false;
}
}
- lua_pop( L, -1 );
- /* If InitWindow is not called in RL.config, call it here. */
- if ( !IsWindowReady() ) {
- InitWindow( 800, 600, "ReiLua" );
- }
- if ( IsWindowReady() ) {
- stateContextInit();
- }
else {
- state->run = false;
+ TraceLog( LOG_ERROR, "%s", "No Lua init found!" );
+ return false;
}
+ lua_pop( L, -1 );
+
+ return state->run;
}
void luaCallInit() {
@@ -1789,6 +1984,10 @@ void luaRegister() {
assingGlobalFunction( "GetPrevDirectoryPath", lcoreGetPrevDirectoryPath );
assingGlobalFunction( "GetWorkingDirectory", lcoreGetWorkingDirectory );
assingGlobalFunction( "GetApplicationDirectory", lcoreGetApplicationDirectory );
+ /* Asset loading functions. */
+ assingGlobalFunction( "BeginAssetLoading", lcoreBeginAssetLoading );
+ assingGlobalFunction( "UpdateAssetLoading", lcoreUpdateAssetLoading );
+ assingGlobalFunction( "EndAssetLoading", lcoreEndAssetLoading );
assingGlobalFunction( "MakeDirectory", lcoreMakeDirectory );
assingGlobalFunction( "ChangeDirectory", lcoreChangeDirectory );
assingGlobalFunction( "IsPathFile", lcoreIsPathFile );
diff --git a/src/main.c b/src/main.c
index f35d2bf..d4d8fd2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,15 @@
#include "main.h"
#include "state.h"
#include "lua_core.h"
+#include "splash.h"
+
+#ifdef _WIN32
+// Forward declarations for Windows console functions
+extern __declspec(dllimport) int __stdcall AllocConsole(void);
+extern __declspec(dllimport) int __stdcall FreeConsole(void);
+extern __declspec(dllimport) void* __stdcall GetStdHandle(unsigned long nStdHandle);
+extern __declspec(dllimport) int __stdcall SetStdHandle(unsigned long nStdHandle, void* hHandle);
+#endif
static inline void printVersion() {
if ( VERSION_DEV ) {
@@ -22,30 +31,92 @@ static inline void printVersion() {
int main( int argn, const char** argc ) {
char basePath[ STRING_LEN ] = { '\0' };
bool interpret_mode = false;
+ bool show_console = false;
+ bool skip_splash = false;
+
+#ifdef _WIN32
+ /* Check for --log and --no-logo arguments */
+ for ( int i = 1; i < argn; i++ ) {
+ if ( strcmp( argc[i], "--log" ) == 0 ) {
+ show_console = true;
+ }
+ if ( strcmp( argc[i], "--no-logo" ) == 0 ) {
+ skip_splash = true;
+ }
+ }
+
+ /* Show or hide console based on --log argument */
+ if ( show_console ) {
+ /* Allocate a console if we don't have one */
+ if ( AllocConsole() ) {
+ freopen( "CONOUT$", "w", stdout );
+ freopen( "CONOUT$", "w", stderr );
+ freopen( "CONIN$", "r", stdin );
+ }
+ }
+ else {
+ /* Hide console window */
+ FreeConsole();
+ }
+#else
+ /* Check for --no-logo on non-Windows platforms */
+ for ( int i = 1; i < argn; i++ ) {
+ if ( strcmp( argc[i], "--no-logo" ) == 0 ) {
+ skip_splash = true;
+ break;
+ }
+ }
+#endif
if ( 1 < argn ) {
- if ( strcmp( argc[1], "--version" ) == 0 || strcmp( argc[1], "-v" ) == 0 ) {
+ /* Skip --log and --no-logo flags to find the actual command */
+ int arg_index = 1;
+ while ( arg_index < argn && ( strcmp( argc[arg_index], "--log" ) == 0 || strcmp( argc[arg_index], "--no-logo" ) == 0 ) ) {
+ arg_index++;
+ }
+
+ if ( arg_index < argn && ( strcmp( argc[arg_index], "--version" ) == 0 || strcmp( argc[arg_index], "-v" ) == 0 ) ) {
printVersion();
return 1;
}
- else if ( strcmp( argc[1], "--help" ) == 0 || strcmp( argc[1], "-h" ) == 0 ) {
- printf( "Usage: ReiLua [Options] [Directory to main.lua or main]\nOptions:\n-h --help\tThis help\n-v --version\tShow ReiLua version\n-i --interpret\tInterpret mode [File name]\n" );
+ else if ( arg_index < argn && ( strcmp( argc[arg_index], "--help" ) == 0 || strcmp( argc[arg_index], "-h" ) == 0 ) ) {
+ printf( "Usage: ReiLua [Options] [Directory to main.lua or main]\nOptions:\n-h --help\tThis help\n-v --version\tShow ReiLua version\n-i --interpret\tInterpret mode [File name]\n--log\t\tShow console for logging\n--no-logo\tSkip splash screens (development)\n" );
return 1;
}
- else if ( strcmp( argc[1], "--interpret" ) == 0 || strcmp( argc[1], "-i" ) == 0 ) {
+ else if ( arg_index < argn && ( strcmp( argc[arg_index], "--interpret" ) == 0 || strcmp( argc[arg_index], "-i" ) == 0 ) ) {
interpret_mode = true;
- if ( 2 < argn ) {
- sprintf( basePath, "%s/%s", GetWorkingDirectory(), argc[2] );
+ if ( arg_index + 1 < argn ) {
+ sprintf( basePath, "%s/%s", GetWorkingDirectory(), argc[arg_index + 1] );
}
}
- else{
- sprintf( basePath, "%s/%s", GetWorkingDirectory(), argc[1] );
+ else if ( arg_index < argn ) {
+ sprintf( basePath, "%s/%s", GetWorkingDirectory(), argc[arg_index] );
+ }
+ else {
+ /* Only flags were provided, use default path search */
+ char testPath[ STRING_LEN ] = { '\0' };
+ sprintf( testPath, "%s/main.lua", GetWorkingDirectory() );
+
+ if ( FileExists( testPath ) ) {
+ sprintf( basePath, "%s", GetWorkingDirectory() );
+ }
+ else {
+ sprintf( basePath, "%s", GetApplicationDirectory() );
+ }
}
}
- /* If no argument given, assume main.lua is in exe directory. */
+ /* If no argument given, check current directory first, then exe directory. */
else {
- sprintf( basePath, "%s", GetApplicationDirectory() );
+ char testPath[ STRING_LEN ] = { '\0' };
+ sprintf( testPath, "%s/main.lua", GetWorkingDirectory() );
+
+ if ( FileExists( testPath ) ) {
+ sprintf( basePath, "%s", GetWorkingDirectory() );
+ }
+ else {
+ sprintf( basePath, "%s", GetApplicationDirectory() );
+ }
}
if ( interpret_mode ) {
@@ -65,15 +136,30 @@ int main( int argn, const char** argc ) {
else {
printVersion();
stateInit( argn, argc, basePath );
- luaCallMain();
- luaCallInit();
+
+ /* Show splash screens if not skipped */
+ if ( !skip_splash ) {
+ splashInit();
+ bool splashDone = false;
+
+ while ( !splashDone && !WindowShouldClose() ) {
+ float delta = GetFrameTime();
+ splashDone = splashUpdate( delta );
+ splashDraw();
+ }
+
+ splashCleanup();
+ }
+
+ /* Now run the main Lua program */
+ state->run = luaCallMain();
while ( state->run ) {
- luaCallUpdate();
- luaCallDraw();
if ( WindowShouldClose() ) {
state->run = false;
}
+ luaCallUpdate();
+ luaCallDraw();
}
luaCallExit();
}
diff --git a/src/splash.c b/src/splash.c
new file mode 100644
index 0000000..185db0c
--- /dev/null
+++ b/src/splash.c
@@ -0,0 +1,198 @@
+#include "main.h"
+#include "state.h"
+#include "splash.h"
+
+#ifdef EMBED_LOGO
+ #include "embedded_logo.h"
+#endif
+
+#define FADE_IN_TIME 0.8f
+#define DISPLAY_TIME 2.5f
+#define FADE_OUT_TIME 0.8f
+#define SPLASH_TOTAL_TIME (FADE_IN_TIME + DISPLAY_TIME + FADE_OUT_TIME)
+
+typedef enum {
+ SPLASH_INDRAJITH,
+ SPLASH_MADE_WITH,
+ SPLASH_DONE
+} SplashState;
+
+static SplashState currentSplash = SPLASH_INDRAJITH;
+static float splashTimer = 0.0f;
+static Texture2D raylibLogo = { 0 };
+static Texture2D reiluaLogo = { 0 };
+static bool logosLoaded = false;
+
+static float getSplashAlpha( float timer ) {
+ if ( timer < FADE_IN_TIME ) {
+ return timer / FADE_IN_TIME;
+ }
+ else if ( timer < FADE_IN_TIME + DISPLAY_TIME ) {
+ return 1.0f;
+ }
+ else {
+ float fadeOut = timer - FADE_IN_TIME - DISPLAY_TIME;
+ return 1.0f - ( fadeOut / FADE_OUT_TIME );
+ }
+}
+
+static void loadSplashLogos() {
+ if ( logosLoaded ) return;
+
+#ifdef EMBED_LOGO
+ /* Load from embedded data */
+ Image raylib_img = LoadImageFromMemory( ".png", embedded_raylib_logo, embedded_raylib_logo_size );
+ raylibLogo = LoadTextureFromImage( raylib_img );
+ UnloadImage( raylib_img );
+
+ Image reilua_img = LoadImageFromMemory( ".png", embedded_reilua_logo, embedded_reilua_logo_size );
+ reiluaLogo = LoadTextureFromImage( reilua_img );
+ UnloadImage( reilua_img );
+#else
+ /* Load from files (development mode) */
+ if ( FileExists( "logo/raylib_logo.png" ) ) {
+ raylibLogo = LoadTexture( "logo/raylib_logo.png" );
+ }
+ if ( FileExists( "logo/reilua_logo.png" ) ) {
+ reiluaLogo = LoadTexture( "logo/reilua_logo.png" );
+ }
+#endif
+
+ logosLoaded = true;
+}
+
+static void unloadSplashLogos() {
+ if ( !logosLoaded ) return;
+
+ UnloadTexture( raylibLogo );
+ UnloadTexture( reiluaLogo );
+ logosLoaded = false;
+}
+
+static void drawIndrajithSplash( float alpha ) {
+ int screenWidth = GetScreenWidth();
+ int screenHeight = GetScreenHeight();
+
+ ClearBackground( (Color){ 230, 41, 55, 255 } ); // Raylib red
+
+ const char* text = "INDRAJITH MAKES GAMES";
+ int fontSize = 48;
+ float spacing = 2.0f;
+
+ Color textColor = WHITE;
+ textColor.a = (unsigned char)(255 * alpha);
+
+ /* Draw text with slight expansion effect during fade in */
+ float scale = 0.95f + (alpha * 0.05f); // Subtle scale from 0.95 to 1.0
+
+ /* Measure text with proper spacing for accurate centering */
+ Vector2 textSize = MeasureTextEx( state->defaultFont, text, fontSize * scale, spacing );
+
+ /* Calculate centered position */
+ Vector2 position = {
+ (float)(screenWidth / 2) - (textSize.x / 2),
+ (float)(screenHeight / 2) - (textSize.y / 2)
+ };
+
+ /* Draw with proper kerning */
+ DrawTextEx( state->defaultFont, text, position, fontSize * scale, spacing, textColor );
+}
+
+static void drawMadeWithSplash( float alpha ) {
+ int screenWidth = GetScreenWidth();
+ int screenHeight = GetScreenHeight();
+
+ ClearBackground( BLACK );
+
+ /* "Made using" text at top */
+ const char* madeText = "Made using";
+ int madeSize = 32;
+ int madeWidth = MeasureText( madeText, madeSize );
+
+ Color textColor = WHITE;
+ textColor.a = (unsigned char)(255 * alpha);
+
+ int textY = screenHeight / 2 - 100;
+ DrawText( madeText, screenWidth / 2 - madeWidth / 2, textY, madeSize, textColor );
+
+ /* Calculate logo sizes and positions - scale down if too large */
+ int maxLogoSize = 200;
+ float raylibScale = 1.0f;
+ float reiluaScale = 1.0f;
+
+ if ( raylibLogo.id > 0 && raylibLogo.width > maxLogoSize ) {
+ raylibScale = (float)maxLogoSize / (float)raylibLogo.width;
+ }
+ if ( reiluaLogo.id > 0 && reiluaLogo.width > maxLogoSize ) {
+ reiluaScale = (float)maxLogoSize / (float)reiluaLogo.width;
+ }
+
+ int raylibWidth = (int)(raylibLogo.width * raylibScale);
+ int raylibHeight = (int)(raylibLogo.height * raylibScale);
+ int reiluaWidth = (int)(reiluaLogo.width * reiluaScale);
+ int reiluaHeight = (int)(reiluaLogo.height * reiluaScale);
+
+ /* Position logos side by side with spacing */
+ int spacing = 40;
+ int totalWidth = raylibWidth + spacing + reiluaWidth;
+ int startX = screenWidth / 2 - totalWidth / 2;
+ int logoY = screenHeight / 2 - 20;
+
+ Color tint = WHITE;
+ tint.a = (unsigned char)(255 * alpha);
+
+ /* Draw Raylib logo */
+ if ( raylibLogo.id > 0 ) {
+ Rectangle source = { 0, 0, (float)raylibLogo.width, (float)raylibLogo.height };
+ Rectangle dest = { (float)startX, (float)logoY, (float)raylibWidth, (float)raylibHeight };
+ DrawTexturePro( raylibLogo, source, dest, (Vector2){ 0, 0 }, 0.0f, tint );
+ }
+
+ /* Draw ReiLua logo */
+ if ( reiluaLogo.id > 0 ) {
+ int reiluaX = startX + raylibWidth + spacing;
+ Rectangle source = { 0, 0, (float)reiluaLogo.width, (float)reiluaLogo.height };
+ Rectangle dest = { (float)reiluaX, (float)logoY, (float)reiluaWidth, (float)reiluaHeight };
+ DrawTexturePro( reiluaLogo, source, dest, (Vector2){ 0, 0 }, 0.0f, tint );
+ }
+}
+
+void splashInit() {
+ loadSplashLogos();
+ currentSplash = SPLASH_INDRAJITH;
+ splashTimer = 0.0f;
+}
+
+bool splashUpdate( float delta ) {
+ splashTimer += delta;
+
+ if ( splashTimer >= SPLASH_TOTAL_TIME ) {
+ splashTimer = 0.0f;
+ currentSplash++;
+ }
+
+ return currentSplash >= SPLASH_DONE;
+}
+
+void splashDraw() {
+ float alpha = getSplashAlpha( splashTimer );
+
+ BeginDrawing();
+
+ switch ( currentSplash ) {
+ case SPLASH_INDRAJITH:
+ drawIndrajithSplash( alpha );
+ break;
+ case SPLASH_MADE_WITH:
+ drawMadeWithSplash( alpha );
+ break;
+ default:
+ break;
+ }
+
+ EndDrawing();
+}
+
+void splashCleanup() {
+ unloadSplashLogos();
+}
diff --git a/src/state.c b/src/state.c
index 3f806d9..d05416a 100644
--- a/src/state.c
+++ b/src/state.c
@@ -4,31 +4,71 @@
#include "textures.h"
#include "models.h"
+#ifdef EMBED_FONT
+ #include "embedded_font.h"
+#endif
+
State* state;
bool stateInit( int argn, const char** argc, const char* basePath ) {
state = malloc( sizeof( State ) );
+
state->basePath = malloc( STRING_LEN * sizeof( char ) );
strncpy( state->basePath, basePath, STRING_LEN - 1 );
+
+ /* Ensure basePath ends with a slash */
+ size_t len = strlen( state->basePath );
+ if ( len > 0 && state->basePath[len - 1] != '/' && state->basePath[len - 1] != '\\' ) {
+ if ( len < STRING_LEN - 2 ) {
+ state->basePath[len] = '/';
+ state->basePath[len + 1] = '\0';
+ }
+ }
+
+ state->hasWindow = true;
+ state->run = true;
+ state->resolution = (Vector2){ 800, 600 };
state->luaState = NULL;
- state->run = luaInit( argn, argc );;
state->logLevelInvalid = LOG_ERROR;
state->gcUnload = true;
state->lineSpacing = 15;
state->mouseOffset = (Vector2){ 0, 0 };
state->mouseScale = (Vector2){ 1, 1 };
+ state->customFontLoaded = false;
-#if defined PLATFORM_DESKTOP_SDL2 || defined PLATFORM_DESKTOP_SDL3
- state->SDL_eventQueue = malloc( PLATFORM_SDL_EVENT_QUEUE_LEN * sizeof( SDL_Event ) );
- state->SDL_eventQueueLen = 0;
-#endif
+ InitWindow( state->resolution.x, state->resolution.y, "ReiLua" );
- return state->run;
-}
+ if ( !IsWindowReady() ) {
+ state->hasWindow = false;
+ state->run = false;
+ }
+ if ( state->run ) {
+ state->run = luaInit( argn, argc );
+ }
+
+ /* Load custom default font */
+#ifdef EMBED_FONT
+ /* Load from embedded data */
+ state->defaultFont = LoadFontFromMemory( ".ttf", embedded_font_data, embedded_font_data_size, 48, NULL, 0 );
+ SetTextureFilter( state->defaultFont.texture, TEXTURE_FILTER_POINT );
+ state->customFontLoaded = true;
+#else
+ /* Load from file (development mode) */
+ char fontPath[STRING_LEN];
+ snprintf( fontPath, STRING_LEN, "%sfonts/Oleaguid.ttf", state->basePath );
+
+ if ( FileExists( fontPath ) ) {
+ state->defaultFont = LoadFontEx( fontPath, 48, NULL, 0 );
+ SetTextureFilter( state->defaultFont.texture, TEXTURE_FILTER_POINT );
+ state->customFontLoaded = true;
+ }
+ else {
+ TraceLog( LOG_WARNING, "Custom font not found at '%s', using default font", fontPath );
+ state->defaultFont = GetFontDefault();
+ state->customFontLoaded = false;
+ }
+#endif
-/* Init after InitWindow. (When there is OpenGL context.) */
-void stateContextInit() {
- state->defaultFont = GetFontDefault();
state->guiFont = GuiGetFont();
state->defaultMaterial = LoadMaterialDefault();
state->defaultTexture = (Texture){ 1, 1, 1, 1, 7 };
@@ -39,6 +79,17 @@ void stateContextInit() {
for ( int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++ ) {
state->RLGLcurrentShaderLocs[i] = defaultShaderLocs[i];
}
+#if defined PLATFORM_DESKTOP_SDL2 || defined PLATFORM_DESKTOP_SDL3
+ state->SDL_eventQueue = malloc( PLATFORM_SDL_EVENT_QUEUE_LEN * sizeof( SDL_Event ) );
+ state->SDL_eventQueueLen = 0;
+#endif
+
+ return state->run;
+}
+
+/* Init after InitWindow. (When there is OpenGL context.) */
+void stateContextInit() {
+ /* This function is no longer needed as initialization is done in stateInit */
}
void stateInitInterpret( int argn, const char** argc ) {
@@ -54,7 +105,11 @@ void stateFree() {
lua_close( state->luaState );
state->luaState = NULL;
}
- if ( IsWindowReady() ) {
+ /* Unload custom font if it was loaded - must be done before CloseWindow */
+ if ( state->hasWindow && state->customFontLoaded ) {
+ UnloadFont( state->defaultFont );
+ }
+ if ( state->hasWindow ) {
CloseWindow();
}
#ifdef PLATFORM_DESKTOP_SDL