summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio.c272
-rw-r--r--src/core.c1908
-rw-r--r--src/lua_core.c1033
-rw-r--r--src/main.c37
-rw-r--r--src/models.c2113
-rw-r--r--src/rgui.c544
-rw-r--r--src/rmath.c978
-rw-r--r--src/shapes.c457
-rw-r--r--src/state.c194
-rw-r--r--src/text.c102
-rw-r--r--src/textures.c1057
11 files changed, 8695 insertions, 0 deletions
diff --git a/src/audio.c b/src/audio.c
new file mode 100644
index 0000000..45ee6c9
--- /dev/null
+++ b/src/audio.c
@@ -0,0 +1,272 @@
+#include "main.h"
+#include "state.h"
+#include "audio.h"
+#include "lua_core.h"
+
+static bool validSound( size_t id ) {
+ if ( id < 0 || state->soundCount < id || state->sounds[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid sound", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static void checkSoundRealloc( int i ) {
+ if ( i == state->soundCount ) {
+ state->soundCount++;
+ }
+
+ if ( state->soundCount == state->soundAlloc ) {
+ state->soundAlloc += ALLOC_PAGE_SIZE;
+ state->sounds = realloc( state->sounds, state->soundAlloc * sizeof( Sound* ) );
+
+ for ( i = state->soundCount; i < state->soundAlloc; i++ ) {
+ state->sounds[i] = NULL;
+ }
+ }
+}
+
+/*
+## Audio - Sounds
+*/
+
+/*
+> sound = RL_LoadSound( string fileName )
+
+Load sound from file
+
+- Failure return -1
+- Success return int
+*/
+int laudioLoadSound( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadSound( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+
+ if ( FileExists( lua_tostring( L, -1 ) ) ) {
+ int i = 0;
+
+ for ( i = 0; i < state->soundCount; i++ ) {
+ if ( state->sounds[i] == NULL ) {
+ break;
+ }
+ }
+ state->sounds[i] = malloc( sizeof( Sound ) );
+ *state->sounds[i] = LoadSound( lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkSoundRealloc( i );
+ }
+
+ return 1;
+}
+
+/*
+> success = RL_PlaySoundMulti( Sound sound )
+
+Play a sound ( Using multichannel buffer pool )
+
+- Failure return false
+- Success return true
+*/
+int laudioPlaySoundMulti( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_PlaySoundMulti( Sound sound )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ if ( !validSound( lua_tointeger( L, -1 ) ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ PlaySoundMulti( *state->sounds[ lua_tointeger( L, -1 ) ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetSoundVolume( Sound sound, float volume )
+
+Set volume for a sound ( 1.0 is max level )
+
+- Failure return false
+- Success return true
+*/
+int laudioSetSoundVolume( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetSoundVolume( Sound sound, float volume )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ if ( !validSound( lua_tointeger( L, -2 ) ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetSoundVolume( *state->sounds[ lua_tointeger( L, -2 ) ], lua_tonumber( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetSoundPitch( Sound sound, float pitch )
+
+Set pitch for a sound ( 1.0 is base level )
+
+- Failure return false
+- Success return true
+*/
+int laudioSetSoundPitch( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetSoundPitch( Sound sound, float pitch )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ if ( !validSound( lua_tointeger( L, -2 ) ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetSoundPitch( *state->sounds[ lua_tointeger( L, -2 ) ], lua_tonumber( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadSound( Sound sound )
+
+Unload sound
+
+- Failure return false
+- Success return true
+*/
+int laudioUnloadSound( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadSound( Sound sound )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validSound( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadSound( *state->sounds[ id ] );
+ state->sounds[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Audio - Music
+*/
+
+/*
+> success = RL_LoadMusicStream( string fileName )
+
+Load music stream from file
+
+- Failure return false
+- Success return true
+*/
+int laudioLoadMusicStream( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadMusicStream( string fileName )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ if ( FileExists( lua_tostring( L, -1 ) ) ) {
+ state->music = LoadMusicStream( lua_tostring( L, -1 ) );
+ state->music.looping = false;
+
+ lua_pushboolean( L, true );
+ }
+ else {
+ lua_pushboolean( L, false );
+ }
+
+ return 1;
+}
+
+/*
+> PlayMusicStream()
+
+Start music playing
+*/
+int laudioPlayMusicStream( lua_State *L ) {
+ PlayMusicStream( state->music );
+
+ return 1;
+}
+
+/*
+> StopMusicStream()
+
+Stop music playing
+*/
+int laudioStopMusicStream( lua_State *L ) {
+ StopMusicStream( state->music );
+
+ return 1;
+}
+
+/*
+> PauseMusicStream()
+
+Pause music playing
+*/
+int laudioPauseMusicStream( lua_State *L ) {
+ PauseMusicStream( state->music );
+
+ return 1;
+}
+
+/*
+> ResumeMusicStream()
+
+Resume playing paused music
+*/
+int laudioResumeMusicStream( lua_State *L ) {
+ ResumeMusicStream( state->music );
+
+ return 1;
+}
+
+/*
+> playing = PlayMusicStream()
+
+Check if music is playing
+
+- Success return bool
+*/
+int laudioIsMusicStreamPlaying( lua_State *L ) {
+ lua_pushboolean( L, IsMusicStreamPlaying( state->music ) );
+
+ return 1;
+}
+
+/*
+> success = RL_SetMusicVolume( float volume )
+
+Set volume for music ( 1.0 is max level )
+
+- Failure return false
+- Success return true
+*/
+int laudioSetMusicVolume( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMusicVolume( float volume )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetMusicVolume( state->music, lua_tonumber( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
diff --git a/src/core.c b/src/core.c
new file mode 100644
index 0000000..91084b1
--- /dev/null
+++ b/src/core.c
@@ -0,0 +1,1908 @@
+#include "main.h"
+#include "state.h"
+#include "core.h"
+#include "textures.h"
+#include "lua_core.h"
+
+static void checkCamera3DRealloc( int i ) {
+ if ( i == state->camera3DCount ) {
+ state->camera3DCount++;
+ }
+
+ if ( state->camera3DCount == state->camera3DAlloc ) {
+ state->camera3DAlloc += ALLOC_PAGE_SIZE;
+ state->camera3Ds = realloc( state->camera3Ds, state->camera3DAlloc * sizeof( Camera3D* ) );
+
+ for ( i = state->camera3DCount; i < state->camera3DAlloc; i++ ) {
+ state->camera3Ds[i] = NULL;
+ }
+ }
+}
+
+static void checkShaderRealloc( int i ) {
+ if ( i == state->shaderCount ) {
+ state->shaderCount++;
+ }
+
+ if ( state->shaderCount == state->shaderAlloc ) {
+ state->shaderAlloc += ALLOC_PAGE_SIZE;
+ state->shaders = realloc( state->shaders, state->shaderAlloc * sizeof( Shader* ) );
+
+ for ( i = state->shaderCount; i < state->shaderAlloc; i++ ) {
+ state->shaders[i] = NULL;
+ }
+ }
+}
+
+bool validCamera3D( size_t id ) {
+ if ( id < 0 || state->camera3DCount < id || state->camera3Ds[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid camera", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static inline bool validShader( size_t id ) {
+ if ( id < 0 || state->shaderCount < id || state->shaders[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid shader", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/*
+## Core - Window
+*/
+
+/*
+> success = RL_SetWindowMonitor( int monitor )
+
+Set monitor for the current window (fullscreen mode)
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowMonitor( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowMonitor( int monitor )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetWindowMonitor( lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> success = RL_SetWindowPosition( Vector2 pos )
+
+Set window position on screen
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowPosition( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowPosition( Vector2 pos )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 pos = uluaGetVector2( L );
+
+ SetWindowPosition( pos.x, pos.y );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> success = RL_SetWindowSize( Vector2 size )
+
+Set window dimensions
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowSize( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowSize( Vector2 size )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 size = uluaGetVector2( L );
+
+ SetWindowSize( (int)size.x, (int)size.y );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> position = RL_GetMonitorPosition( int monitor )
+
+Get specified monitor position
+
+- Failure return nil
+- Success return Vector2
+*/
+int lcoreGetMonitorPosition( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetMonitorPosition( int monitor )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector2 pos = GetMonitorPosition( lua_tointeger( L, -1 ) );
+ uluaPushVector2( L, pos );
+
+ return 1;
+}
+
+/*
+> size = RL_GetMonitorSize( int monitor )
+
+Get specified monitor size
+
+- Failure return nil
+- Success return Vector2
+*/
+int lcoreGetMonitorSize( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetMonitorSize( int monitor )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector2 size = (Vector2){ GetMonitorWidth( lua_tointeger( L, -1 ) ), GetMonitorHeight( lua_tointeger( L, -1 ) ) };
+ uluaPushVector2( L, size );
+
+ return 1;
+}
+
+/*
+> position = RL_GetWindowPosition()
+
+Get window position on monitor
+
+- Success return Vector2
+*/
+int lcoreGetWindowPosition( lua_State *L ) {
+ Vector2 pos = GetWindowPosition();
+ uluaPushVector2( L, pos );
+
+ return 1;
+}
+
+/*
+> size = RL_GetWindowPosition()
+
+Get window size
+
+- Success return Vector2
+*/
+int lcoreGetWindowSize( lua_State *L ) {
+ Vector2 size = (Vector2){ GetScreenWidth(), GetScreenHeight() };
+ uluaPushVector2( L, size );
+
+ return 1;
+}
+
+/*
+> success = RL_SetWindowState( int flag )
+
+Set window configuration state using flags ( FLAG_FULLSCREEN_MODE, FLAG_WINDOW_RESIZABLE... )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowState( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowState( int flags )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetWindowState( (unsigned int)lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> state = RL_IsWindowState( int flag ) )
+
+Check if one specific window flag is enabled ( FLAG_FULLSCREEN_MODE, FLAG_WINDOW_RESIZABLE... )
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsWindowState( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsWindowState( int flags )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsWindowState( (unsigned int)lua_tointeger( L, -1 ) ) );
+
+ return 1;
+}
+
+/*
+> resized = RL_ClearWindowState( int flag )
+
+Clear window configuration state flags ( FLAG_FULLSCREEN_MODE, FLAG_WINDOW_RESIZABLE... )
+
+- Success return bool
+*/
+int lcoreClearWindowState( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ClearWindowState( int flag )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ ClearWindowState( (unsigned int)lua_tointeger( L, -1 ) );
+
+ return 1;
+}
+
+/*
+> resized = RL_IsWindowResized()
+
+Check if window has been resized from last frame
+
+- Success return bool
+*/
+int lcoreIsWindowResized( lua_State *L ) {
+ lua_pushboolean( L, IsWindowResized() );
+
+ return 1;
+}
+
+/*
+> success = RL_SetWindowIcon( Image image )
+
+Set icon for window ( Only PLATFORM_DESKTOP )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowIcon( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowIcon( Image image )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetWindowIcon( *state->images[ imageId ] );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> success = RL_SetWindowTitle( string title )
+
+Set title for window ( Only PLATFORM_DESKTOP )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetWindowTitle( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetWindowTitle( string title )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetWindowTitle( lua_tostring( L, -1 ) );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+## Core - Timing
+*/
+
+/*
+> success = RL_SetTargetFPS( int fps )
+
+Set target FPS ( maximum )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetTargetFPS( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetTargetFPS( int fps )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetTargetFPS( lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+ return 1;
+}
+
+/*
+> RL_GetFrameTime()
+
+Get time in seconds for last frame drawn ( Delta time )
+*/
+int lcoreGetFrameTime( lua_State *L ) {
+ lua_pushnumber( L, GetFrameTime() );
+
+ return 1;
+}
+
+/*
+> RL_GetTime()
+
+Get elapsed time in seconds since InitWindow()
+*/
+int lcoreGetTime( lua_State *L ) {
+ lua_pushnumber( L, GetTime() );
+
+ return 1;
+}
+
+/*
+## Core - Misc
+*/
+
+/*
+> success = RL_TraceLog( int logLevel, string text )
+
+Show trace log messages ( LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR... )
+
+- Failure return false
+- Success return true
+*/
+int lcoreTraceLog( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_TraceLog( int logLevel, string text )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ TraceLog( lua_tointeger( L, -2 ), "%s", lua_tostring( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_OpenURL( string url )
+
+Open URL with default system browser ( If available )
+
+- Failure return false
+- Success return true
+*/
+int lcoreOpenURL( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_OpenURL( string url )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ OpenURL( lua_tostring( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Core - Cursor
+*/
+
+/*
+> RL_ShowCursor()
+
+Shows cursor
+*/
+int lcoreShowCursor( lua_State *L ) {
+ ShowCursor();
+
+ return 0;
+}
+
+/*
+> RL_HideCursor()
+
+Hides cursor
+*/
+int lcoreHideCursor( lua_State *L ) {
+ HideCursor();
+
+ return 0;
+}
+
+/*
+> hidden = RL_IsCursorHidden()
+
+Check if cursor is not visible
+
+- Success return bool
+*/
+int lcoreIsCursorHidden( lua_State *L ) {
+ lua_pushboolean( L, IsCursorHidden() );
+
+ return 1;
+}
+
+/*
+> RL_EnableCursor()
+
+Enables cursor (unlock cursor)
+*/
+int lcoreEnableCursor( lua_State *L ) {
+ EnableCursor();
+
+ return 0;
+}
+
+/*
+> RL_DisableCursor()
+
+Disables cursor (lock cursor)
+*/
+int lcoreDisableCursor( lua_State *L ) {
+ DisableCursor();
+
+ return 0;
+}
+
+/*
+> onSreen = RL_IsCursorOnScreen()
+
+Check if cursor is on the screen
+
+- Success return bool
+*/
+int lcoreIsCursorOnScreen( lua_State *L ) {
+ lua_pushboolean( L, IsCursorOnScreen() );
+
+ return 1;
+}
+
+/*
+## Core - Drawing
+*/
+
+/*
+> success = RL_ClearBackground( Color color )
+
+Set background color ( framebuffer clear color )
+
+- Failure return false
+- Success return true
+*/
+int lcoreClearBackground( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ClearBackground( Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ ClearBackground( color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_BeginBlendMode( int mode )
+
+Begin blending mode ( BLEND_ALPHA, BLEND_ADDITIVE, BLEND_MULTIPLIED... )
+
+- Failure return false
+- Success return true
+*/
+int lcoreBeginBlendMode( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_BeginBlendMode( int mode )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ BeginBlendMode( lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> RL_EndBlendMode()
+
+End blending mode ( reset to default: BLEND_ALPHA )
+*/
+int lcoreEndBlendMode( lua_State *L ) {
+ EndBlendMode();
+
+ return 1;
+}
+
+/*
+> success = RL_BeginScissorMode( Rectangle rectange )
+
+Begin scissor mode ( define screen area for following drawing )
+
+- Failure return false
+- Success return true
+*/
+int lcoreBeginScissorMode( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_BeginScissorMode( Rectangle rectange )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Rectangle rect = uluaGetRectangle( L );
+
+ BeginScissorMode( rect.x, rect.y, rect.width, rect.height );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> RL_EndScissorMode()
+
+End scissor mode
+*/
+int lcoreEndScissorMode( lua_State *L ) {
+ EndScissorMode();
+
+ return 1;
+}
+
+/*
+## Core - Shader
+*/
+
+/*
+> shader = RL_LoadShader( string vsFileName, string fsFileName )
+
+Load shader from files and bind default locations
+
+- Failure return -1
+- Success return int
+*/
+int lcoreLoadShader( lua_State *L ) {
+ // if ( !lua_isstring( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ // TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadShader( string vsFileName, string fsFileName )" );
+ // lua_pushinteger( L, -1 );
+ // return 1;
+ // }
+
+ char fsFileName[ STRING_LEN ] = { '\0' };
+ char vsFileName[ STRING_LEN ] = { '\0' };
+
+ if ( lua_isstring( L, -1 ) ) {
+ if ( FileExists( lua_tostring( L, -1 ) ) ) {
+ strcpy( fsFileName, lua_tostring( L, -1 ) );
+ }
+ }
+ if ( lua_isstring( L, -2 ) ) {
+ if ( FileExists( lua_tostring( L, -2 ) ) ) {
+ strcpy( vsFileName, lua_tostring( L, -2 ) );
+ }
+ }
+
+ int i = 0;
+
+ for ( i = 0; i < state->shaderCount; i++ ) {
+ if ( state->shaders[i] == NULL ) {
+ break;
+ }
+ }
+ state->shaders[i] = malloc( sizeof( Shader ) );
+ // *state->shaders[i] = LoadShader( lua_tostring( L, -2 ), lua_tostring( L, -1 ) );
+ // *state->shaders[i] = LoadShader( vsFileName, fsFileName );
+ *state->shaders[i] = LoadShader( 0, fsFileName );
+ lua_pushinteger( L, i );
+ checkShaderRealloc( i );
+
+ return 1;
+}
+
+/*
+> shader = RL_LoadShaderFromMemory( string vsCode, string fsCode )
+
+Load shader from code strings and bind default locations
+
+- Failure return -1
+- Success return int
+*/
+
+//TODO Should also allow only one shader.
+int lcoreLoadShaderFromMemory( lua_State *L ) {
+ if ( !lua_isstring( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadShaderFromMemory( string vsCode, string fsCode )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->shaderCount; i++ ) {
+ if ( state->shaders[i] == NULL ) {
+ break;
+ }
+ }
+ state->shaders[i] = malloc( sizeof( Shader ) );
+ *state->shaders[i] = LoadShaderFromMemory( lua_tostring( L, -2 ), lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkShaderRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_BeginShaderMode( Shader shader )
+
+Begin custom shader drawing
+
+- Failure return false
+- Success return true
+*/
+int lcoreBeginShaderMode( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_BeginShaderMode( Shader shader )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t shaderId = lua_tointeger( L, -1 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ BeginShaderMode( *state->shaders[ shaderId ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> EndShaderMode()
+
+End custom shader drawing ( use default shader )
+*/
+int lcoreEndShaderMode( lua_State *L ) {
+ EndShaderMode();
+
+ return 1;
+}
+
+/*
+> location = RL_GetShaderLocation( Shader shader, string uniformName )
+
+Get shader uniform location
+
+- Failure return -1
+- Success return int
+*/
+int lcoreGetShaderLocation( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetShaderLocation( Shader shader, string uniformName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ size_t shaderId = lua_tointeger( L, -2 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ lua_pushinteger( L, GetShaderLocation( *state->shaders[ shaderId ], lua_tostring( L, -1 ) ) );
+
+ return 1;
+}
+
+/*
+> location = RL_GetShaderLocationAttrib( Shader shader, string attribName )
+
+Get shader attribute location
+
+- Failure return -1
+- Success return int
+*/
+int lcoreGetShaderLocationAttrib( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetShaderLocationAttrib( Shader shader, string attribName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ size_t shaderId = lua_tointeger( L, -2 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ lua_pushinteger( L, GetShaderLocationAttrib( *state->shaders[ shaderId ], lua_tostring( L, -1 ) ) );
+
+ return 1;
+}
+
+/*
+> success = RL_SetShaderValueMatrix( Shader shader, int locIndex, Matrix mat )
+
+Set shader uniform value ( matrix 4x4 )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetShaderValueMatrix( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetShaderValueMatrix( Shader shader, int locIndex, Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ int locIndex = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t shaderId = lua_tointeger( L, -1 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetShaderValueMatrix( *state->shaders[ shaderId ], locIndex, mat );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetShaderValueTexture( Shader shader, int locIndex, Texture2D texture )
+
+Set shader uniform value for texture ( sampler2d )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetShaderValueTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetShaderValueTexture( Shader shader, int locIndex, Texture2D texture )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t textureId = lua_tointeger( L, -1 );
+ int locIndex = lua_tointeger( L, -2 );
+ size_t shaderId = lua_tointeger( L, -3 );
+
+ if ( !validShader( shaderId ) || !validTexture( textureId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ SetShaderValueTexture( *state->shaders[ shaderId ], locIndex, *state->textures[ textureId ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetShaderValue( Shader shader, int locIndex, number{} values, int uniformType )
+
+Set shader uniform value
+NOTE: Even one value should be in table
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetShaderValue( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetShaderValue( Shader shader, int locIndex, number{} values, int uniformType )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int uniformType = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+
+ /* Read values. */
+ size_t valueCount = uluaGetTableLen( L );
+ float floats[ valueCount ];
+ int ints[ valueCount ];
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ floats[i] = lua_tonumber( L, -1 );
+ ints[i] = lua_tointeger( L, -1 );
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+ /* Read values end. */
+
+ int locIndex = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t shaderId = lua_tointeger( L, -1 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ if ( uniformType == SHADER_UNIFORM_FLOAT || uniformType == SHADER_UNIFORM_VEC2
+ || uniformType == SHADER_UNIFORM_VEC3 || uniformType == SHADER_UNIFORM_VEC4 ) {
+ SetShaderValue( *state->shaders[ shaderId ], locIndex, floats, uniformType );
+ }
+ else {
+ SetShaderValue( *state->shaders[ shaderId ], locIndex, ints, uniformType );
+ }
+
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetShaderValueV( Shader shader, int locIndex, number{} values, int uniformType, int count )
+
+Set shader uniform value vector
+NOTE: Even one value should be in table
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetShaderValueV( lua_State *L ) {
+ if ( !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetShaderValueV( Shader shader, int locIndex, number{} values, int uniformType, int count )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int count = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int uniformType = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+
+ /* Read values. */
+ size_t valueCount = uluaGetTableLen( L );
+ float floats[ valueCount * count ];
+ int ints[ valueCount * count ];
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ floats[i] = lua_tonumber( L, -1 );
+ ints[i] = lua_tointeger( L, -1 );
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+ /* Read values end. */
+
+ int locIndex = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t shaderId = lua_tointeger( L, -1 );
+
+ if ( !validShader( shaderId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ if ( uniformType == SHADER_UNIFORM_FLOAT || uniformType == SHADER_UNIFORM_VEC2
+ || uniformType == SHADER_UNIFORM_VEC3 || uniformType == SHADER_UNIFORM_VEC4 ) {
+ SetShaderValueV( *state->shaders[ shaderId ], locIndex, floats, uniformType, count );
+ }
+ else {
+ SetShaderValueV( *state->shaders[ shaderId ], locIndex, ints, uniformType, count );
+ }
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadShader( Shader shader )
+
+Unload shader from GPU memory ( VRAM )
+
+- Failure return false
+- Success return true
+*/
+int lcoreUnloadShader( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadShader( Shader shader )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validShader( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadShader( *state->shaders[ id ] );
+ state->shaders[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Core - Input
+*/
+
+/*
+> pressed = RL_IsKeyPressed( int key )
+
+Detect if a key has been pressed once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsKeyPressed( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsKeyPressed( int key )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsKeyPressed( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> pressed = RL_IsKeyDown( int key )
+
+Detect if a key is being pressed
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsKeyDown( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsKeyDown( int key )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsKeyDown( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> released = RL_IsKeyReleased( int key )
+
+Detect if a key has been released once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsKeyReleased( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsKeyReleased( int key )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsKeyReleased( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> keycode = RL_GetKeyPressed()
+
+Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
+
+- Success return int
+*/
+int lcoreGetKeyPressed( lua_State *L ) {
+ lua_pushinteger( L, GetKeyPressed() );
+
+ return 1;
+}
+
+/*
+> unicode = RL_GetCharPressed()
+
+Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
+
+- Success return int
+*/
+int lcoreGetCharPressed( lua_State *L ) {
+ lua_pushinteger( L, GetCharPressed() );
+
+ return 1;
+}
+
+/*
+> RL_SetExitKey( int key )
+
+Set a custom key to exit program ( default is ESC )
+*/
+int lcoreSetExitKey( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetExitKey( int key )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ SetExitKey( lua_tointeger( L, -1 ) );
+
+ return 1;
+}
+
+/*
+> available = RL_IsGamepadAvailable( int gamepad )
+
+Detect if a gamepad is available
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsGamepadAvailable( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsGamepadAvailable( int gamepad )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsGamepadAvailable( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> pressed = RL_IsGamepadButtonPressed( int gamepad, int button )
+
+Detect if a gamepad button has been pressed once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsGamepadButtonPressed( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsGamepadButtonPressed( int gamepad, int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsGamepadButtonPressed( lua_tointeger( L, -2 ), lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> pressed = RL_IsGamepadButtonDown( int gamepad, int button )
+
+Detect if a gamepad button is being pressed
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsGamepadButtonDown( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsGamepadButtonDown( int gamepad, int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsGamepadButtonDown( lua_tointeger( L, -2 ), lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> released = RL_IsGamepadButtonReleased( int gamepad, int button )
+
+Detect if a gamepad button has been released once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsGamepadButtonReleased( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsGamepadButtonReleased( int gamepad, int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsGamepadButtonReleased( lua_tointeger( L, -2 ), lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> count = RL_GetGamepadAxisCount( int gamepad )
+
+Return gamepad axis count for a gamepad
+
+- Failure return false
+- Success return int
+*/
+int lcoreGetGamepadAxisCount( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetGamepadAxisCount( int gamepad )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushinteger( L, GetGamepadAxisCount( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> value = RL_GetGamepadAxisMovement( int gamepad, int axis )
+
+Return axis movement value for a gamepad axis
+
+- Failure return false
+- Success return float
+*/
+int lcoreGetGamepadAxisMovement( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetGamepadAxisMovement( int gamepad, int axis )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushnumber( L, GetGamepadAxisMovement( lua_tointeger( L, -2 ), lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> name = RL_GetGamepadName( int gamepad )
+
+Return gamepad internal name id
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetGamepadName( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetGamepadName( int gamepad )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetGamepadName( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> pressed = RL_IsMouseButtonPressed( int button )
+
+Detect if a mouse button has been pressed once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsMouseButtonPressed( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsMouseButtonPressed( int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsMouseButtonPressed( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> pressed = RL_IsMouseButtonDown( int button )
+
+Detect if a mouse button is being pressed
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsMouseButtonDown( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsMouseButtonDown( int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsMouseButtonDown( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> released = RL_IsMouseButtonReleased( int button )
+
+Detect if a mouse button has been released once
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsMouseButtonReleased( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsMouseButtonReleased( int button )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsMouseButtonReleased( lua_tointeger( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> position = RL_GetMousePosition()
+
+Returns mouse position
+
+- Success return Vector2
+*/
+int lcoreGetMousePosition( lua_State *L ) {
+ uluaPushVector2( L, GetMousePosition() );
+ return 1;
+}
+
+/*
+> position = RL_GetMouseDelta()
+
+Get mouse delta between frames
+
+- Success return Vector2
+*/
+int lcoreGetMouseDelta( lua_State *L ) {
+ uluaPushVector2( L, GetMouseDelta() );
+ return 1;
+}
+
+/*
+> movement = RL_GetMouseWheelMove()
+
+Returns mouse wheel movement Y
+
+- Success return float
+*/
+int lcoreGetMouseWheelMove( lua_State *L ) {
+ lua_pushnumber( L, GetMouseWheelMove() );
+ return 1;
+}
+
+/*
+> success = RL_SetMousePosition( Vector2 position )
+
+Set mouse position XY
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetMousePosition( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMousePosition( Vector2 position )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 pos = uluaGetVector2( L );
+
+ SetMousePosition( pos.x, pos.y );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Core - File
+*/
+
+/*
+> path = RL_GetBasePath()
+
+Return game directory ( where main.lua is located )
+
+- Success return string
+*/
+int lcoreGetBasePath( lua_State *L ) {
+ lua_pushstring( L, state->exePath );
+
+ return 1;
+}
+
+/*
+> fileExists = RL_FileExists( string fileName )
+
+Check if file exists
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreFileExists( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_FileExists( string fileName )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, FileExists( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> dirExists = RL_DirectoryExists( string dirPath )
+
+Check if a directory path exists
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreDirectoryExists( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DirectoryExists( string dirPath )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, DirectoryExists( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> hasFileExtension = RL_IsFileExtension( string fileName, string ext )
+
+Check file extension ( Including point: .png, .wav )
+
+- Failure return nil
+- Success return bool
+*/
+int lcoreIsFileExtension( lua_State *L ) {
+ if ( !lua_isstring( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_IsFileExtension( string fileName, string ext )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ lua_pushboolean( L, IsFileExtension( lua_tostring( L, -2 ), lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> extension = RL_GetFileExtension( string fileName )
+
+Get pointer to extension for a filename string ( Includes dot: '.png' )
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetFileExtension( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetFileExtension( string fileName )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetFileExtension( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> filePath = RL_GetFileName( string filePath )
+
+Get pointer to filename for a path string
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetFileName( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetFileName( string filePath )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetFileName( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> filePath = RL_GetFileNameWithoutExt( string filePath )
+
+Get filename string without extension ( Uses static string )
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetFileNameWithoutExt( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetFileNameWithoutExt( string filePath )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetFileNameWithoutExt( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> filePath = RL_GetDirectoryPath( string filePath )
+
+Get full path for a given fileName with path ( Uses static string )
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetDirectoryPath( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetDirectoryPath( string filePath )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetDirectoryPath( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> filePath = RL_GetPrevDirectoryPath( string dirPath )
+
+Get previous directory path for a given path ( Uses static string )
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetPrevDirectoryPath( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetPrevDirectoryPath( string dirPath )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetPrevDirectoryPath( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+> filePath = RL_GetWorkingDirectory()
+
+Get current working directory ( Uses static string )
+
+- Failure return false
+- Success return string
+*/
+int lcoreGetWorkingDirectory( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetWorkingDirectory()" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushstring( L, GetWorkingDirectory() );
+ return 1;
+}
+
+/*
+> fileNames = RL_GetDirectoryFiles( string dirPath )
+
+Get filenames in a directory path
+
+- Failure return false
+- Success return string{}
+*/
+int lcoreGetDirectoryFiles( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetDirectoryFiles( string dirPath )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int count = 0;
+ char **strings = GetDirectoryFiles( lua_tostring( L, -1 ), &count );
+
+ lua_createtable( L, count, 0 );
+
+ for ( int i = 0; i < count; ++i ) {
+ lua_pushstring( L, strings[i] );
+ lua_rawseti( L, -2, i+1 );
+ }
+ ClearDirectoryFiles();
+
+ return 1;
+}
+
+/*
+> time = RL_GetFileModTime( string fileName )
+
+Get file modification time ( Last write time )
+
+- Failure return false
+- Success return int
+*/
+int lcoreGetFileModTime( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetFileModTime( string fileName )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushinteger( L, GetFileModTime( lua_tostring( L, -1 ) ) );
+ return 1;
+}
+
+/*
+## Core - Camera
+*/
+
+/*
+> camera = RL_CreateCamera3D()
+
+Return camera3D id set to default configuration
+
+- Success return int
+*/
+int lcoreCreateCamera3D( lua_State *L ) {
+ int i = 0;
+
+ for ( i = 0; i < state->camera3DCount; i++ ) {
+ if ( state->camera3Ds[i] == NULL ) {
+ break;
+ }
+ }
+ state->camera3Ds[i] = malloc( sizeof( Camera3D ) );
+ state->camera3Ds[i]->fovy = 45.0f;
+ state->camera3Ds[i]->projection = CAMERA_PERSPECTIVE;
+ SetCameraMode( *state->camera3Ds[i], CAMERA_CUSTOM );
+
+ lua_pushinteger( L, i );
+ checkCamera3DRealloc(i);
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadCamera3D( int Camera3D )
+
+Unload Camera3D
+
+- Failure return false
+- Success return true
+*/
+int lcoreUnloadCamera3D( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadCamera3D( int Camera3D )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ free( state->camera3Ds[ id ] );
+ state->camera3Ds[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_BeginMode3D( camera3D camera )
+
+Initializes 3D mode with custom camera ( 3D )
+
+- Failure return false
+- Success return true
+*/
+int lcoreBeginMode3D( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_BeginMode3D( camera3D camera )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ BeginMode3D( *state->camera3Ds[ id ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> RL_EndMode3D()
+
+Ends 3D mode and returns to default 2D orthographic mode
+*/
+int lcoreEndMode3D( lua_State *L ) {
+ EndMode3D();
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DPosition( camera3D camera, Vector3 position )
+
+Set camera position ( Remember to call "RL_UpdateCamera3D()" to apply changes )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DPosition( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DPosition( camera3D camera, Vector3 position )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 pos = uluaGetVector3( L );
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->camera3Ds[ cameraId ]->position = pos;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DTarget( camera3D camera, Vector3 target )
+
+Set camera target it looks-at
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DTarget( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DTarget( camera3D camera, Vector3 target )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 target = uluaGetVector3( L );
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->camera3Ds[ cameraId ]->target = target;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DUp( camera3D camera, Vector3 up )
+
+Set camera up vector ( Rotation over it's axis )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DUp( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DUp( camera3D camera, Vector3 up )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 up = uluaGetVector3( L );
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->camera3Ds[ cameraId ]->up = up;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DFovy( camera3D camera, Vector3 fovy )
+
+Set camera field-of-view apperture in Y ( degrees ) in perspective, used as near plane width in orthographic
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DFovy( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DFovy( camera3D camera, Vector3 fovy )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->camera3Ds[ cameraId ]->fovy = lua_tonumber( L, -1 );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DProjection( camera3D camera, int projection )
+
+Set camera projection mode ( CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DProjection( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DProjection( camera3D camera, int projection )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->camera3Ds[ cameraId ]->projection = lua_tointeger( L, -1 );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetCamera3DMode( camera3D camera, int mode )
+
+Set camera mode ( CAMERA_CUSTOM, CAMERA_FREE, CAMERA_ORBITAL... )
+
+- Failure return false
+- Success return true
+*/
+int lcoreSetCamera3DMode( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetCamera3DMode( camera3D camera, int mode )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -2 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetCameraMode( *state->camera3Ds[ cameraId ], lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> position = RL_GetCamera3DPosition( camera3D camera )
+
+Get camera position
+
+- Failure return nil
+- Success return Vector3
+*/
+int lcoreGetCamera3DPosition( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCamera3DPosition( camera3D camera )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+
+ uluaPushVector3( L, state->camera3Ds[ cameraId ]->position );
+
+ return 1;
+}
+
+/*
+> target = RL_GetCamera3DTarget( camera3D camera )
+
+Get camera target it looks-at
+
+- Failure return nil
+- Success return Vector3
+*/
+int lcoreGetCamera3DTarget( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCamera3DTarget( camera3D camera )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+
+ uluaPushVector3( L, state->camera3Ds[ cameraId ]->target );
+
+ return 1;
+}
+
+/*
+> up = RL_GetCamera3DUp( camera3D camera )
+
+Get camera up vector ( Rotation over it's axis )
+
+- Failure return nil
+- Success return Vector3
+*/
+int lcoreGetCamera3DUp( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCamera3DUp( camera3D camera )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+
+ uluaPushVector3( L, state->camera3Ds[ cameraId ]->up );
+
+ return 1;
+}
+
+/*
+> fovy = RL_GetCamera3DFovy( camera3D camera )
+
+Get camera field-of-view apperture in Y ( degrees ) in perspective, used as near plane width in orthographic
+
+- Failure return nil
+- Success return float
+*/
+int lcoreGetCamera3DFovy( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCamera3DFovy( camera3D camera )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+
+ lua_pushnumber( L, state->camera3Ds[ cameraId ]->fovy );
+
+ return 1;
+}
+
+/*
+> projection = RL_GetCamera3DProjection( camera3D camera )
+
+Get camera projection mode
+
+- Failure return nil
+- Success return int
+*/
+int lcoreGetCamera3DProjection( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCamera3DProjection( camera3D camera )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+
+ lua_pushinteger( L, state->camera3Ds[ cameraId ]->projection );
+
+ return 1;
+}
+
+/*
+> success = RL_UpdateCamera3D( camera3D camera )
+
+Update camera position for selected mode
+
+- Failure return false
+- Success return true
+*/
+int lcoreUpdateCamera3D( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UpdateCamera3D( camera3D camera )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ UpdateCamera( state->camera3Ds[ cameraId ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
diff --git a/src/lua_core.c b/src/lua_core.c
new file mode 100644
index 0000000..ab59c1d
--- /dev/null
+++ b/src/lua_core.c
@@ -0,0 +1,1033 @@
+#include "main.h"
+#include "state.h"
+#include "lua_core.h"
+#include "core.h"
+#include "shapes.h"
+#include "textures.h"
+#include "models.h"
+#include "text.h"
+#include "audio.h"
+#include "rmath.h"
+#include "rgui.h"
+
+static void assignGlobalInt( int value, const char *name ) {
+ lua_State *L = state->luaState;
+ lua_pushinteger( L, value );
+ lua_setglobal( L, name );
+}
+
+static void assignGlobalFloat( float value, const char *name ) {
+ lua_State *L = state->luaState;
+ lua_pushnumber( L, value );
+ lua_setglobal( L, name );
+}
+
+static void assignGlobalColor( Color color, const char *name ) {
+ lua_State *L = state->luaState;
+ uluaPushColor( L, color );
+ lua_setglobal( L, name );
+}
+
+void defineGlobals() {
+/*DOC_START*/
+ /* Keys */
+ assignGlobalInt( KEY_ENTER, "KEY_ENTER" );
+ assignGlobalInt( KEY_SPACE, "KEY_SPACE" );
+ assignGlobalInt( KEY_ESCAPE, "KEY_ESCAPE" );
+ assignGlobalInt( KEY_ENTER, "KEY_ENTER" );
+ assignGlobalInt( KEY_TAB, "KEY_TAB" );
+ assignGlobalInt( KEY_BACKSPACE, "KEY_BACKSPACE" );
+ assignGlobalInt( KEY_INSERT, "KEY_INSERT" );
+ assignGlobalInt( KEY_DELETE, "KEY_DELETE" );
+ assignGlobalInt( KEY_RIGHT, "KEY_RIGHT" );
+ assignGlobalInt( KEY_LEFT, "KEY_LEFT" );
+ assignGlobalInt( KEY_DOWN, "KEY_DOWN" );
+ assignGlobalInt( KEY_UP, "KEY_UP" );
+ /* WindowFlags */
+ assignGlobalInt( FLAG_VSYNC_HINT, "FLAG_VSYNC_HINT" );
+ assignGlobalInt( FLAG_FULLSCREEN_MODE, "FLAG_FULLSCREEN_MODE" );
+ assignGlobalInt( FLAG_WINDOW_RESIZABLE, "FLAG_WINDOW_RESIZABLE" );
+ assignGlobalInt( FLAG_WINDOW_UNDECORATED, "FLAG_WINDOW_UNDECORATED" );
+ assignGlobalInt( FLAG_WINDOW_HIDDEN, "FLAG_WINDOW_HIDDEN" );
+ assignGlobalInt( FLAG_WINDOW_MINIMIZED, "FLAG_WINDOW_MINIMIZED" );
+ assignGlobalInt( FLAG_WINDOW_MAXIMIZED, "FLAG_WINDOW_MAXIMIZED" );
+ assignGlobalInt( FLAG_WINDOW_UNFOCUSED, "FLAG_WINDOW_UNFOCUSED" );
+ assignGlobalInt( FLAG_WINDOW_TOPMOST, "FLAG_WINDOW_TOPMOST" );
+ assignGlobalInt( FLAG_WINDOW_ALWAYS_RUN, "FLAG_WINDOW_ALWAYS_RUN" );
+ assignGlobalInt( FLAG_WINDOW_TRANSPARENT, "FLAG_WINDOW_TRANSPARENT" );
+ assignGlobalInt( FLAG_WINDOW_HIGHDPI, "FLAG_WINDOW_HIGHDPI" );
+ assignGlobalInt( FLAG_MSAA_4X_HINT, "FLAG_MSAA_4X_HINT" );
+ assignGlobalInt( FLAG_INTERLACED_HINT, "FLAG_INTERLACED_HINT" );
+ /* BlendModes */
+ assignGlobalInt( BLEND_ALPHA, "BLEND_ALPHA" );
+ assignGlobalInt( BLEND_ADDITIVE, "BLEND_ADDITIVE" );
+ assignGlobalInt( BLEND_MULTIPLIED, "BLEND_MULTIPLIED" );
+ assignGlobalInt( BLEND_ADD_COLORS, "BLEND_ADD_COLORS" );
+ assignGlobalInt( BLEND_SUBTRACT_COLORS, "BLEND_SUBTRACT_COLORS" );
+ assignGlobalInt( BLEND_CUSTOM, "BLEND_CUSTOM" );
+ /* TextureModes */
+ assignGlobalInt( TEXTURE_SOURCE_TEXTURE, "TEXTURE_SOURCE_TEXTURE" );
+ assignGlobalInt( TEXTURE_SOURCE_RENDER_TEXTURE, "TEXTURE_SOURCE_RENDER_TEXTURE" );
+ /* CameraProjections */
+ assignGlobalInt( CAMERA_PERSPECTIVE, "CAMERA_PERSPECTIVE" );
+ assignGlobalInt( CAMERA_ORTHOGRAPHIC, "CAMERA_ORTHOGRAPHIC" );
+ /* CameraMode */
+ assignGlobalInt( CAMERA_CUSTOM, "CAMERA_CUSTOM" );
+ assignGlobalInt( CAMERA_FREE, "CAMERA_FREE" );
+ assignGlobalInt( CAMERA_ORBITAL, "CAMERA_ORBITAL" );
+ assignGlobalInt( CAMERA_FIRST_PERSON, "CAMERA_FIRST_PERSON" );
+ assignGlobalInt( CAMERA_THIRD_PERSON, "CAMERA_THIRD_PERSON" );
+ /* MapTypes */
+ assignGlobalInt( MATERIAL_MAP_ALBEDO, "MATERIAL_MAP_ALBEDO" );
+ assignGlobalInt( MATERIAL_MAP_METALNESS, "MATERIAL_MAP_METALNESS" );
+ assignGlobalInt( MATERIAL_MAP_NORMAL, "MATERIAL_MAP_NORMAL" );
+ assignGlobalInt( MATERIAL_MAP_ROUGHNESS, "MATERIAL_MAP_ROUGHNESS" );
+ assignGlobalInt( MATERIAL_MAP_OCCLUSION, "MATERIAL_MAP_OCCLUSION" );
+ assignGlobalInt( MATERIAL_MAP_EMISSION, "MATERIAL_MAP_EMISSION" );
+ assignGlobalInt( MATERIAL_MAP_HEIGHT, "MATERIAL_MAP_HEIGHT" );
+ assignGlobalInt( MATERIAL_MAP_CUBEMAP, "MATERIAL_MAP_CUBEMAP" );
+ assignGlobalInt( MATERIAL_MAP_IRRADIANCE, "MATERIAL_MAP_IRRADIANCE" );
+ assignGlobalInt( MATERIAL_MAP_PREFILTER, "MATERIAL_MAP_PREFILTER" );
+ assignGlobalInt( MATERIAL_MAP_BRDF, "MATERIAL_MAP_BRDF" );
+ /* TextureFilters */
+ assignGlobalInt( TEXTURE_FILTER_POINT, "TEXTURE_FILTER_POINT" );
+ assignGlobalInt( TEXTURE_FILTER_BILINEAR, "TEXTURE_FILTER_BILINEAR" );
+ assignGlobalInt( TEXTURE_FILTER_TRILINEAR, "TEXTURE_FILTER_TRILINEAR" );
+ assignGlobalInt( TEXTURE_FILTER_ANISOTROPIC_4X, "TEXTURE_FILTER_ANISOTROPIC_4X" );
+ assignGlobalInt( TEXTURE_FILTER_ANISOTROPIC_8X, "TEXTURE_FILTER_ANISOTROPIC_8X" );
+ assignGlobalInt( TEXTURE_FILTER_ANISOTROPIC_16X, "TEXTURE_FILTER_ANISOTROPIC_16X" );
+ /* TextureWrapModes */
+ assignGlobalInt( TEXTURE_WRAP_REPEAT, "TEXTURE_WRAP_REPEAT" );
+ assignGlobalInt( TEXTURE_WRAP_CLAMP, "TEXTURE_WRAP_CLAMP" );
+ assignGlobalInt( TEXTURE_WRAP_MIRROR_REPEAT, "TEXTURE_WRAP_MIRROR_REPEAT" );
+ assignGlobalInt( TEXTURE_WRAP_MIRROR_CLAMP, "TEXTURE_WRAP_MIRROR_CLAMP" );
+ /* TraceLogLevel */
+ assignGlobalInt( LOG_ALL, "LOG_ALL" );
+ assignGlobalInt( LOG_TRACE, "LOG_TRACE" );
+ assignGlobalInt( LOG_DEBUG, "LOG_DEBUG" );
+ assignGlobalInt( LOG_INFO, "LOG_INFO" );
+ assignGlobalInt( LOG_WARNING, "LOG_WARNING" );
+ assignGlobalInt( LOG_ERROR, "LOG_ERROR" );
+ assignGlobalInt( LOG_FATAL, "LOG_FATAL" );
+ assignGlobalInt( LOG_NONE, "LOG_NONE" );
+ /* N-patchLayout */
+ assignGlobalInt( NPATCH_NINE_PATCH, "NPATCH_NINE_PATCH" );
+ assignGlobalInt( NPATCH_THREE_PATCH_VERTICAL, "NPATCH_THREE_PATCH_VERTICAL" );
+ assignGlobalInt( NPATCH_THREE_PATCH_HORIZONTAL, "NPATCH_THREE_PATCH_HORIZONTAL" );
+ /* Shader location index */
+ assignGlobalInt( SHADER_LOC_VERTEX_POSITION, "SHADER_LOC_VERTEX_POSITION" );
+ assignGlobalInt( SHADER_LOC_VERTEX_TEXCOORD01, "SHADER_LOC_VERTEX_TEXCOORD01" );
+ assignGlobalInt( SHADER_LOC_VERTEX_TEXCOORD02, "SHADER_LOC_VERTEX_TEXCOORD02" );
+ assignGlobalInt( SHADER_LOC_VERTEX_NORMAL, "SHADER_LOC_VERTEX_NORMAL" );
+ assignGlobalInt( SHADER_LOC_VERTEX_TANGENT, "SHADER_LOC_VERTEX_TANGENT" );
+ assignGlobalInt( SHADER_LOC_VERTEX_COLOR, "SHADER_LOC_VERTEX_COLOR" );
+ assignGlobalInt( SHADER_LOC_MATRIX_MVP, "SHADER_LOC_MATRIX_MVP" );
+ assignGlobalInt( SHADER_LOC_MATRIX_VIEW, "SHADER_LOC_MATRIX_VIEW" );
+ assignGlobalInt( SHADER_LOC_MATRIX_PROJECTION, "SHADER_LOC_MATRIX_PROJECTION" );
+ assignGlobalInt( SHADER_LOC_MATRIX_MODEL, "SHADER_LOC_MATRIX_MODEL" );
+ assignGlobalInt( SHADER_LOC_MATRIX_NORMAL, "SHADER_LOC_MATRIX_NORMAL" );
+ assignGlobalInt( SHADER_LOC_VECTOR_VIEW, "SHADER_LOC_VECTOR_VIEW" );
+ assignGlobalInt( SHADER_LOC_COLOR_DIFFUSE, "SHADER_LOC_COLOR_DIFFUSE" );
+ assignGlobalInt( SHADER_LOC_COLOR_SPECULAR, "SHADER_LOC_COLOR_SPECULAR" );
+ assignGlobalInt( SHADER_LOC_COLOR_AMBIENT, "SHADER_LOC_COLOR_AMBIENT" );
+ assignGlobalInt( SHADER_LOC_MAP_ALBEDO, "SHADER_LOC_MAP_ALBEDO" );
+ assignGlobalInt( SHADER_LOC_MAP_METALNESS, "SHADER_LOC_MAP_METALNESS" );
+ assignGlobalInt( SHADER_LOC_MAP_NORMAL, "SHADER_LOC_MAP_NORMAL" );
+ assignGlobalInt( SHADER_LOC_MAP_ROUGHNESS, "SHADER_LOC_MAP_ROUGHNESS" );
+ assignGlobalInt( SHADER_LOC_MAP_OCCLUSION, "SHADER_LOC_MAP_OCCLUSION" );
+ assignGlobalInt( SHADER_LOC_MAP_EMISSION, "SHADER_LOC_MAP_EMISSION" );
+ assignGlobalInt( SHADER_LOC_MAP_HEIGHT, "SHADER_LOC_MAP_HEIGHT" );
+ assignGlobalInt( SHADER_LOC_MAP_CUBEMAP, "SHADER_LOC_MAP_CUBEMAP" );
+ assignGlobalInt( SHADER_LOC_MAP_IRRADIANCE, "SHADER_LOC_MAP_IRRADIANCE" );
+ assignGlobalInt( SHADER_LOC_MAP_PREFILTER, "SHADER_LOC_MAP_PREFILTER" );
+ assignGlobalInt( SHADER_LOC_MAP_BRDF, "SHADER_LOC_MAP_BRDF" );
+ /* Shader uniform data type */
+ assignGlobalInt( SHADER_UNIFORM_FLOAT, "SHADER_UNIFORM_FLOAT" );
+ assignGlobalInt( SHADER_UNIFORM_VEC2, "SHADER_UNIFORM_VEC2" );
+ assignGlobalInt( SHADER_UNIFORM_VEC3, "SHADER_UNIFORM_VEC3" );
+ assignGlobalInt( SHADER_UNIFORM_VEC4, "SHADER_UNIFORM_VEC4" );
+ assignGlobalInt( SHADER_UNIFORM_INT, "SHADER_UNIFORM_INT" );
+ assignGlobalInt( SHADER_UNIFORM_IVEC2, "SHADER_UNIFORM_IVEC2" );
+ assignGlobalInt( SHADER_UNIFORM_IVEC3, "SHADER_UNIFORM_IVEC3" );
+ assignGlobalInt( SHADER_UNIFORM_IVEC4, "SHADER_UNIFORM_IVEC4" );
+ assignGlobalInt( SHADER_UNIFORM_SAMPLER2D, "SHADER_UNIFORM_SAMPLER2D" );
+ /* Shader attribute data types */
+ assignGlobalInt( SHADER_ATTRIB_FLOAT, "SHADER_ATTRIB_FLOAT" );
+ assignGlobalInt( SHADER_ATTRIB_VEC2, "SHADER_ATTRIB_VEC2" );
+ assignGlobalInt( SHADER_ATTRIB_VEC3, "SHADER_ATTRIB_VEC3" );
+ assignGlobalInt( SHADER_ATTRIB_VEC4, "SHADER_ATTRIB_VEC4" );
+ /* Colors */
+ assignGlobalColor( WHITE, "WHITE" );
+ assignGlobalColor( BLACK, "BLACK" );
+ assignGlobalColor( BLANK, "BLANK" );
+ assignGlobalColor( MAGENTA, "MAGENTA" );
+ assignGlobalColor( RAYWHITE, "RAYWHITE" );
+ assignGlobalColor( RED, "RED" );
+ assignGlobalColor( GREEN, "GREEN" );
+ assignGlobalColor( BLUE, "BLUE" );
+ /* Math */
+ assignGlobalFloat( PI, "PI" );
+/*DOC_END*/
+}
+
+bool luaInit() {
+ state->luaState = luaL_newstate();
+
+ luaL_openlibs( state->luaState );
+
+ if ( state->luaState == NULL ) {
+ TraceLog( LOG_WARNING, "%s", "Failed to init Lua" );
+
+ return false;
+ }
+ luaRegister();
+ defineGlobals();
+
+ return luaCallMain();
+}
+
+int luaTraceback( lua_State *L ) {
+ lua_getglobal( L, "debug" );
+
+ if ( !lua_istable( L, -1 ) ) {
+ lua_pop( L, 1 );
+ return 1;
+ }
+
+ lua_getfield( L, -1, "traceback" );
+
+ if ( !lua_isfunction( L, -1 ) ) {
+ lua_pop(L, 2);
+ return 1;
+ }
+
+ lua_pushvalue( L, 1 ); // pass error message
+ lua_pushinteger( L, 2 ); // skip this function and traceback
+ lua_call( L, 2, 1 ); // call debug.traceback
+
+ return 1;
+}
+
+bool luaCallMain() {
+ lua_State *L = state->luaState;
+
+ char path[ STRING_LEN ] = { '\0' };
+
+ sprintf( path, "%smain.lua", state->exePath );
+
+ luaL_dofile( L, path );
+
+ /* Check errors in main.lua */
+ if ( lua_tostring( state->luaState, -1 ) ) {
+ TraceLog( LOG_WARNING, "Lua error: %s\n", lua_tostring( state->luaState, -1 ) );
+ }
+
+ lua_pushcfunction( L, luaTraceback );
+ int tracebackidx = lua_gettop( L );
+
+ lua_getglobal( L, "init" );
+
+ if ( lua_isfunction( L, -1 ) ) {
+ if ( lua_pcall( L, 0, 0, tracebackidx ) != 0 ) {
+ TraceLog( LOG_WARNING, "Lua error: %s", lua_tostring( L, -1 ) );
+ return false;
+ }
+ }
+ else {
+ TraceLog( LOG_WARNING, "%s", "No Lua main found!" );
+ return false;
+ }
+
+ return true;
+}
+
+void luaCallProcess() {
+ lua_State *L = state->luaState;
+
+ lua_pushcfunction( L, luaTraceback );
+ int tracebackidx = lua_gettop(L);
+
+ lua_getglobal( L, "process" );
+
+ if ( lua_isfunction( L, -1 ) ) {
+ lua_pushnumber( L, GetFrameTime() );
+
+ if ( lua_pcall( L, 1, 0, tracebackidx ) != 0 ) {
+ TraceLog( LOG_WARNING, "Lua error: %s", lua_tostring( L, -1 ) );
+ state->run = false;
+ return;
+ }
+ }
+ // else {
+ // TraceLog( LOG_WARNING, "%s", "No Lua process found!" );
+ // state->run = false;
+ // return;
+ // }
+ lua_pop( L, -1 );
+}
+
+void luaCallDraw() {
+ lua_State *L = state->luaState;
+ lua_pushcfunction( L, luaTraceback );
+ int tracebackidx = lua_gettop(L);
+
+ lua_getglobal( L, "draw" );
+
+ if ( lua_isfunction( L, -1 ) ) {
+ BeginDrawing();
+
+ if ( lua_pcall( L, 0, 0, tracebackidx ) != 0 ) {
+ TraceLog( LOG_WARNING, "Lua error: %s", lua_tostring( L, -1 ) );
+ // state->run = false;
+ return;
+ }
+
+ EndDrawing();
+ }
+ // else {
+ // TraceLog( LOG_WARNING, "%s", "No Lua render found!" );
+ // state->run = false;
+ // return;
+ // }
+ lua_pop( L, -1 );
+}
+
+void luaRegister() {
+ lua_State *L = state->luaState;
+
+ /* Core. */
+ /* Window. */
+ lua_register( L, "RL_SetWindowMonitor", lcoreSetWindowMonitor );
+ lua_register( L, "RL_SetWindowPosition", lcoreSetWindowPosition );
+ lua_register( L, "RL_SetWindowSize", lcoreSetWindowSize );
+ lua_register( L, "RL_GetMonitorPosition", lcoreGetMonitorPosition );
+ lua_register( L, "RL_GetMonitorSize", lcoreGetMonitorSize );
+ lua_register( L, "RL_GetWindowPosition", lcoreGetWindowPosition );
+ lua_register( L, "RL_GetWindowSize", lcoreGetWindowSize );
+ lua_register( L, "RL_SetWindowState", lcoreSetWindowState );
+ lua_register( L, "RL_IsWindowState", lcoreIsWindowState );
+ lua_register( L, "RL_ClearWindowState", lcoreClearWindowState );
+ lua_register( L, "RL_IsWindowResized", lcoreIsWindowResized );
+ lua_register( L, "RL_SetWindowIcon", lcoreSetWindowIcon );
+ lua_register( L, "RL_SetWindowTitle", lcoreSetWindowTitle );
+ /* Timing. */
+ lua_register( L, "RL_SetTargetFPS", lcoreSetTargetFPS );
+ lua_register( L, "RL_GetFrameTime", lcoreGetFrameTime );
+ lua_register( L, "RL_GetTime", lcoreGetTime );
+ /* Misc. */
+ lua_register( L, "RL_TraceLog", lcoreTraceLog );
+ lua_register( L, "RL_OpenURL", lcoreOpenURL );
+ /* Cursor. */
+ lua_register( L, "RL_ShowCursor", lcoreShowCursor );
+ lua_register( L, "RL_HideCursor", lcoreHideCursor );
+ lua_register( L, "RL_IsCursorHidden", lcoreIsCursorHidden );
+ lua_register( L, "RL_EnableCursor", lcoreEnableCursor );
+ lua_register( L, "RL_DisableCursor", lcoreDisableCursor );
+ lua_register( L, "RL_IsCursorOnScreen", lcoreIsCursorOnScreen );
+ /* Drawing. */
+ lua_register( L, "RL_ClearBackground", lcoreClearBackground );
+ lua_register( L, "RL_BeginBlendMode", lcoreBeginBlendMode );
+ lua_register( L, "RL_EndBlendMode", lcoreEndBlendMode );
+ lua_register( L, "RL_BeginScissorMode", lcoreBeginScissorMode );
+ lua_register( L, "RL_EndScissorMode", lcoreEndScissorMode );
+ /* Shader. */
+ lua_register( L, "RL_LoadShader", lcoreLoadShader );
+ lua_register( L, "RL_LoadShaderFromMemory", lcoreLoadShaderFromMemory );
+ lua_register( L, "RL_BeginShaderMode", lcoreBeginShaderMode );
+ lua_register( L, "RL_EndShaderMode", lcoreEndShaderMode );
+ lua_register( L, "RL_GetShaderLocation", lcoreGetShaderLocation );
+ lua_register( L, "RL_GetShaderLocationAttrib", lcoreGetShaderLocationAttrib );
+ lua_register( L, "RL_SetShaderValueMatrix", lcoreSetShaderValueMatrix );
+ lua_register( L, "RL_SetShaderValueTexture", lcoreSetShaderValueTexture );
+ lua_register( L, "RL_SetShaderValue", lcoreSetShaderValue );
+ lua_register( L, "RL_SetShaderValueV", lcoreSetShaderValueV );
+ lua_register( L, "RL_UnloadShader", lcoreUnloadShader );
+ /* File. */
+ lua_register( L, "RL_GetBasePath", lcoreGetBasePath );
+ lua_register( L, "RL_FileExists", lcoreFileExists );
+ lua_register( L, "RL_DirectoryExists", lcoreDirectoryExists );
+ lua_register( L, "RL_IsFileExtension", lcoreIsFileExtension );
+ lua_register( L, "RL_GetFileExtension", lcoreGetFileExtension );
+ lua_register( L, "RL_GetFileName", lcoreGetFileName );
+ lua_register( L, "RL_GetFileNameWithoutExt", lcoreGetFileNameWithoutExt );
+ lua_register( L, "RL_GetDirectoryPath", lcoreGetDirectoryPath );
+ lua_register( L, "RL_GetPrevDirectoryPath", lcoreGetPrevDirectoryPath );
+ lua_register( L, "RL_GetWorkingDirectory", lcoreGetWorkingDirectory );
+ lua_register( L, "RL_GetDirectoryFiles", lcoreGetDirectoryFiles );
+ lua_register( L, "RL_GetFileModTime", lcoreGetFileModTime );
+ /* Camera. */
+ lua_register( L, "RL_CreateCamera3D", lcoreCreateCamera3D );
+ lua_register( L, "RL_UnloadCamera3D", lcoreUnloadCamera3D );
+ lua_register( L, "RL_BeginMode3D", lcoreBeginMode3D );
+ lua_register( L, "RL_EndMode3D", lcoreEndMode3D );
+ lua_register( L, "RL_SetCamera3DPosition", lcoreSetCamera3DPosition );
+ lua_register( L, "RL_SetCamera3DTarget", lcoreSetCamera3DTarget );
+ lua_register( L, "RL_SetCamera3DUp", lcoreSetCamera3DUp );
+ lua_register( L, "RL_SetCamera3DFovy", lcoreSetCamera3DFovy );
+ lua_register( L, "RL_SetCamera3DProjection", lcoreSetCamera3DProjection );
+ lua_register( L, "RL_GetCamera3DPosition", lcoreGetCamera3DPosition );
+ lua_register( L, "RL_GetCamera3DTarget", lcoreGetCamera3DTarget );
+ lua_register( L, "RL_GetCamera3DUp", lcoreGetCamera3DUp );
+ lua_register( L, "RL_GetCamera3DFovy", lcoreGetCamera3DFovy );
+ lua_register( L, "RL_GetCamera3DProjection", lcoreGetCamera3DProjection );
+ lua_register( L, "RL_UpdateCamera3D", lcoreUpdateCamera3D );
+ lua_register( L, "RL_SetCamera3DMode", lcoreSetCamera3DMode );
+ /* Input. */
+ lua_register( L, "RL_IsKeyPressed", lcoreIsKeyPressed );
+ lua_register( L, "RL_IsKeyDown", lcoreIsKeyDown );
+ lua_register( L, "RL_IsKeyReleased", lcoreIsKeyReleased );
+ lua_register( L, "RL_GetKeyPressed", lcoreGetKeyPressed );
+ lua_register( L, "RL_GetCharPressed", lcoreGetCharPressed );
+ lua_register( L, "RL_SetExitKey", lcoreSetExitKey );
+ lua_register( L, "RL_IsGamepadAvailable", lcoreIsGamepadAvailable );
+ lua_register( L, "RL_IsGamepadButtonPressed", lcoreIsGamepadButtonPressed );
+ lua_register( L, "RL_IsGamepadButtonDown", lcoreIsGamepadButtonDown );
+ lua_register( L, "RL_IsGamepadButtonReleased", lcoreIsGamepadButtonReleased );
+ lua_register( L, "RL_GetGamepadAxisCount", lcoreGetGamepadAxisCount );
+ lua_register( L, "RL_GetGamepadAxisMovement", lcoreGetGamepadAxisMovement );
+ lua_register( L, "RL_GetGamepadName", lcoreGetGamepadName );
+ lua_register( L, "RL_IsMouseButtonPressed", lcoreIsMouseButtonPressed );
+ lua_register( L, "RL_IsMouseButtonDown", lcoreIsMouseButtonDown );
+ lua_register( L, "RL_IsMouseButtonReleased", lcoreIsMouseButtonReleased );
+ lua_register( L, "RL_GetMousePosition", lcoreGetMousePosition );
+ lua_register( L, "RL_GetMouseDelta", lcoreGetMouseDelta );
+ lua_register( L, "RL_GetMouseWheelMove", lcoreGetMouseWheelMove );
+ lua_register( L, "RL_SetMousePosition", lcoreSetMousePosition );
+
+ /* Shapes. */
+ /* Drawing. */
+ lua_register( L, "RL_DrawPixel", lshapesDrawPixel );
+ lua_register( L, "RL_DrawLine", lshapesDrawLine );
+ lua_register( L, "RL_DrawCircle", lshapesDrawCircle );
+ lua_register( L, "RL_DrawCircleLines", lshapesDrawCircleLines );
+ lua_register( L, "RL_DrawRectangle", lshapesDrawRectangle );
+ lua_register( L, "RL_DrawRectanglePro", lshapesDrawRectanglePro );
+ lua_register( L, "RL_DrawTriangle", lshapesDrawTriangle );
+ lua_register( L, "RL_DrawTriangleLines", lshapesDrawTriangleLines );
+ /* Collision. */
+ lua_register( L, "RL_CheckCollisionRecs", lshapesCheckCollisionRecs );
+ lua_register( L, "RL_CheckCollisionCircles", lshapesCheckCollisionCircles );
+ lua_register( L, "RL_CheckCollisionCircleRec", lshapesCheckCollisionCircleRec );
+ lua_register( L, "RL_CheckCollisionPointRec", lshapesCheckCollisionPointRec );
+ lua_register( L, "RL_CheckCollisionPointCircle", lshapesCheckCollisionPointCircle );
+ lua_register( L, "RL_CheckCollisionPointTriangle", lshapesCheckCollisionPointTriangle );
+ lua_register( L, "RL_CheckCollisionLines", lshapesCheckCollisionLines );
+ lua_register( L, "RL_CheckCollisionPointLine", lshapesCheckCollisionPointLine );
+ lua_register( L, "RL_GetCollisionRec", lshapesGetCollisionRec );
+
+ /* Textures. */
+ /* File. */
+ lua_register( L, "RL_LoadImage", ltexturesLoadImage );
+ lua_register( L, "RL_GenImageColor", ltexturesGenImageColor );
+ lua_register( L, "RL_UnloadImage", ltexturesUnloadImage );
+ lua_register( L, "RL_LoadTexture", ltexturesLoadTexture );
+ lua_register( L, "RL_LoadTextureFromImage", ltexturesLoadTextureFromImage );
+ lua_register( L, "RL_UnloadTexture", ltexturesUnloadTexture );
+ lua_register( L, "RL_LoadRenderTexture", ltexturesLoadRenderTexture );
+ lua_register( L, "RL_UnloadRenderTexture", ltexturesUnloadRenderTexture );
+ /* Image Drawing. */
+ lua_register( L, "RL_ImageClearBackground", ltexturesImageClearBackground );
+ lua_register( L, "RL_ImageDrawPixel", ltexturesImageDrawPixel );
+ lua_register( L, "RL_ImageDrawLine", ltexturesImageDrawLine );
+ lua_register( L, "RL_ImageDrawCircle", ltexturesImageDrawCircle );
+ lua_register( L, "RL_ImageDrawRectangle", ltexturesImageDrawRectangle );
+ lua_register( L, "RL_ImageDrawRectangleLines", ltexturesImageDrawRectangleLines );
+ lua_register( L, "RL_ImageDraw", ltexturesImageDraw );
+ lua_register( L, "RL_ImageDrawTextEx", ltexturesImageDrawTextEx );
+ /* Texture Drawing. */
+ lua_register( L, "RL_DrawTexture", ltexturesDrawTexture );
+ lua_register( L, "RL_DrawTextureRec", ltexturesDrawTextureRec );
+ lua_register( L, "RL_DrawTextureTiled", ltexturesDrawTextureTiled );
+ lua_register( L, "RL_DrawTexturePro", ltexturesDrawTexturePro );
+ lua_register( L, "RL_DrawTextureNPatch", ltexturesDrawTextureNPatch );
+ lua_register( L, "RL_DrawTexturePoly", ltexturesDrawTexturePoly );
+ lua_register( L, "RL_BeginTextureMode", ltexturesBeginTextureMode );
+ lua_register( L, "RL_EndTextureMode", ltexturesEndTextureMode );
+ lua_register( L, "RL_SetTextureSource", ltexturesSetTextureSource );
+ lua_register( L, "RL_GetTextureSource", ltexturesGetTextureSource );
+ /* Conf. */
+ lua_register( L, "RL_GenTextureMipmaps", ltexturesGenTextureMipmaps );
+ lua_register( L, "RL_SetTextureFilter", ltexturesSetTextureFilter );
+ lua_register( L, "RL_SetTextureWrap", ltexturesSetTextureWrap );
+ lua_register( L, "RL_GetTextureSize", ltexturesGetTextureSize );
+
+ /* Models. */
+ /* Basic. */
+ lua_register( L, "RL_DrawLine3D", lmodelsDrawLine3D );
+ lua_register( L, "RL_DrawPoint3D", lmodelsDrawPoint3D );
+ lua_register( L, "RL_DrawCircle3D", lmodelsDrawCircle3D );
+ lua_register( L, "RL_DrawTriangle3D", lmodelsDrawTriangle3D );
+ lua_register( L, "RL_DrawCube", lmodelsDrawCube );
+ lua_register( L, "RL_DrawCubeWires", lmodelsDrawCubeWires );
+ lua_register( L, "RL_DrawCubeTexture", lmodelsDrawCubeTexture );
+ lua_register( L, "RL_DrawSphere", lmodelsDrawSphere );
+ lua_register( L, "RL_DrawSphereEx", lmodelsDrawSphereEx );
+ lua_register( L, "RL_DrawSphereWires", lmodelsDrawSphereWires );
+ lua_register( L, "RL_DrawCylinder", lmodelsDrawCylinder );
+ lua_register( L, "RL_DrawCylinderEx", lmodelsDrawCylinderEx );
+ lua_register( L, "RL_DrawCylinderWires", lmodelsDrawCylinderWires );
+ lua_register( L, "RL_DrawCylinderWiresEx", lmodelsDrawCylinderWiresEx );
+ lua_register( L, "RL_DrawPlane", lmodelsDrawPlane );
+ lua_register( L, "RL_DrawQuad3DTexture", lmodelDrawQuad3DTexture );
+ lua_register( L, "RL_DrawRay", lmodelsDrawRay );
+ lua_register( L, "RL_DrawGrid", lmodelsDrawGrid );
+ /* Mesh. */
+ lua_register( L, "RL_GenMeshPoly", lmodelsGenMeshPoly );
+ lua_register( L, "RL_GenMeshPlane", lmodelsGenMeshPlane );
+ lua_register( L, "RL_GenMeshCube", lmodelsGenMeshCube );
+ lua_register( L, "RL_GenMeshSphere", lmodelsGenMeshSphere );
+ lua_register( L, "RL_GenMeshCylinder", lmodelsGenMeshCylinder );
+ lua_register( L, "RL_GenMeshCone", lmodelsGenMeshCone );
+ lua_register( L, "RL_GenMeshTorus", lmodelsGenMeshTorus );
+ lua_register( L, "RL_GenMeshKnot", lmodelsGenMeshKnot );
+ lua_register( L, "RL_GenMeshHeightmap", lmodelsGenMeshHeightmap );
+ lua_register( L, "RL_GenMeshCustom", lmodelsGenMeshCustom );
+ lua_register( L, "RL_UnloadMesh", lmodelsUnloadMesh );
+ lua_register( L, "RL_DrawMesh", lmodelsDrawMesh );
+ lua_register( L, "RL_DrawMeshInstanced", lmodelsDrawMeshInstanced );
+ lua_register( L, "RL_SetMeshColor", lmodelsSetMeshColor );
+ /* Material. */
+ lua_register( L, "RL_LoadMaterialDefault", lmodelsLoadMaterialDefault );
+ lua_register( L, "RL_CreateMaterial", lmodelsCreateMaterial );
+ lua_register( L, "RL_UnloadMaterial", lmodelsUnloadMaterial );
+ lua_register( L, "RL_SetMaterialTexture", lmodelsSetMaterialTexture );
+ lua_register( L, "RL_SetMaterialColor", lmodelsSetMaterialColor );
+ lua_register( L, "RL_SetMaterialValue", lmodelsSetMaterialValue );
+ /* Model. */
+ lua_register( L, "RL_LoadModel", lmodelsLoadModel );
+ lua_register( L, "RL_LoadModelFromMesh", lmodelsLoadModelFromMesh );
+ lua_register( L, "RL_UnloadModel", lmodelsUnloadModel );
+ lua_register( L, "RL_DrawModel", lmodelsDrawModel );
+ lua_register( L, "RL_DrawModelEx", lmodelsDrawModelEx );
+ lua_register( L, "RL_SetModelMaterial", lmodelsSetModelMaterial );
+ lua_register( L, "RL_SetModelMeshMaterial", lmodelsSetModelMeshMaterial );
+ lua_register( L, "RL_DrawBillboard", lmodelsDrawBillboard );
+ lua_register( L, "RL_DrawBillboardRec", lmodelsDrawBillboardRec );
+ /* Animations. */
+ lua_register( L, "RL_LoadModelAnimations", lmodelsLoadModelAnimations );
+ lua_register( L, "RL_UpdateModelAnimation", lmodelsUpdateModelAnimation );
+ lua_register( L, "RL_GetModelAnimationBoneCount", lmodelsGetModelAnimationBoneCount );
+ lua_register( L, "RL_GetModelAnimationFrameCount", lmodelsGetModelAnimationFrameCount );
+ /* Collision. */
+ lua_register( L, "RL_CheckCollisionSpheres", lmodelsCheckCollisionSpheres );
+ lua_register( L, "RL_CheckCollisionBoxes", lmodelsCheckCollisionBoxes );
+ lua_register( L, "RL_CheckCollisionBoxSphere", lmodelsCheckCollisionBoxSphere );
+ lua_register( L, "RL_GetRayCollisionSphere", lmodelsGetRayCollisionSphere );
+ lua_register( L, "RL_GetRayCollisionBox", lmodelsGetRayCollisionBox );
+ lua_register( L, "RL_GetRayCollisionModel", lmodelsGetRayCollisionModel );
+ lua_register( L, "RL_GetRayCollisionMesh", lmodelsGetRayCollisionMesh );
+ lua_register( L, "RL_GetRayCollisionTriangle", lmodelsGetRayCollisionTriangle );
+ lua_register( L, "RL_GetRayCollisionQuad", lmodelsGetRayCollisionQuad );
+
+ /* Text. */
+ /* Loading. */
+ lua_register( L, "RL_LoadFont", lmodelsLoadFont );
+ /* Drawing. */
+ lua_register( L, "RL_DrawText", ltextDrawText );
+
+ /* Audio. */
+ /* Sound. */
+ lua_register( L, "RL_LoadSound", laudioLoadSound );
+ lua_register( L, "RL_PlaySoundMulti", laudioPlaySoundMulti );
+ lua_register( L, "RL_SetSoundVolume", laudioSetSoundVolume );
+ lua_register( L, "RL_SetSoundPitch", laudioSetSoundPitch );
+ lua_register( L, "RL_UnloadSound", laudioUnloadSound );
+ /* Music. */
+ lua_register( L, "RL_LoadMusicStream", laudioLoadMusicStream );
+ lua_register( L, "RL_PlayMusicStream", laudioPlayMusicStream );
+ lua_register( L, "RL_StopMusicStream", laudioStopMusicStream );
+ lua_register( L, "RL_PauseMusicStream", laudioPauseMusicStream );
+ lua_register( L, "RL_ResumeMusicStream", laudioResumeMusicStream );
+ lua_register( L, "RL_IsMusicStreamPlaying", laudioIsMusicStreamPlaying );
+ lua_register( L, "RL_SetMusicVolume", laudioSetMusicVolume );
+
+ /* Math. */
+ /* Vector2. */
+ lua_register( L, "RL_Vector2Add", lmathVector2Add );
+ lua_register( L, "RL_Vector2Subtract", lmathVector2Subtract );
+ lua_register( L, "RL_Vector2Multiply", lmathVector2Multiply );
+ lua_register( L, "RL_Vector2Length", lmathVector2Length );
+ lua_register( L, "RL_Vector2DotProduct", lmathVector2DotProduct );
+ lua_register( L, "RL_Vector2Distance", lmathVector2Distance );
+ lua_register( L, "RL_Vector2Angle", lmathVector2Angle );
+ lua_register( L, "RL_Vector2Normalize", lmathVector2Normalize );
+ lua_register( L, "RL_Vector2Lerp", lmathVector2Lerp );
+ lua_register( L, "RL_Vector2Reflect", lmathVector2Reflect );
+ lua_register( L, "RL_Vector2Rotate", lmathVector2Rotate );
+ lua_register( L, "RL_Vector2MoveTowards", lmathVector2MoveTowards );
+ /* Vector3. */
+ lua_register( L, "RL_Vector3Add", lmathVector3Add );
+ lua_register( L, "RL_Vector3Subtract", lmathVector3Subtract );
+ lua_register( L, "RL_Vector3Multiply", lmathVector3Multiply );
+ lua_register( L, "RL_Vector3CrossProduct", lmathVector3CrossProduct );
+ lua_register( L, "RL_Vector3Perpendicular", lmathVector3Perpendicular );
+ lua_register( L, "RL_Vector3Length", lmathVector3Length );
+ lua_register( L, "RL_Vector3LengthSqr", lmathVector3LengthSqr );
+ lua_register( L, "RL_Vector3DotProduct", lmathVector3DotProduct );
+ lua_register( L, "RL_Vector3Distance", lmathVector3Distance );
+ lua_register( L, "RL_Vector3Normalize", lmathVector3Normalize );
+ lua_register( L, "RL_Vector3OrthoNormalize", lmathVector3OrthoNormalize );
+ lua_register( L, "RL_Vector3Transform", lmathVector3Transform );
+ lua_register( L, "RL_Vector3RotateByQuaternion", lmathVector3RotateByQuaternion );
+ lua_register( L, "RL_Vector3Lerp", lmathVector3Lerp );
+ lua_register( L, "RL_Vector3Reflect", lmathVector3Reflect );
+ /* Matrix. */
+ lua_register( L, "RL_MatrixDeterminant", lmathMatrixDeterminant );
+ lua_register( L, "RL_MatrixTranspose", lmathMatrixTranspose );
+ lua_register( L, "RL_MatrixInvert", lmathMatrixInvert );
+ lua_register( L, "RL_MatrixNormalize", lmathMatrixNormalize );
+ lua_register( L, "RL_MatrixIdentity", lmathMatrixIdentity );
+ lua_register( L, "RL_MatrixAdd", lmathMatrixAdd );
+ lua_register( L, "RL_MatrixSubtract", lmathMatrixSubtract );
+ lua_register( L, "RL_MatrixMultiply", lmathMatrixMultiply );
+ lua_register( L, "RL_MatrixTranslate", lmathMatrixTranslate );
+ lua_register( L, "RL_MatrixRotate", lmathMatrixRotate );
+ lua_register( L, "RL_MatrixScale", lmathMatrixScale );
+ lua_register( L, "RL_MatrixFrustum", lmathMatrixFrustum );
+ lua_register( L, "RL_MatrixPerspective", lmathMatrixPerspective );
+ lua_register( L, "RL_MatrixOrtho", lmathMatrixOrtho );
+ lua_register( L, "RL_MatrixLookAt", lmathMatrixLookAt );
+
+ /* Gui. */
+ /* Global. */
+ lua_register( L, "RL_GuiEnable", lguiGuiEnable );
+ lua_register( L, "RL_GuiDisable", lguiGuiDisable );
+ lua_register( L, "RL_GuiLock", lguiGuiLock );
+ lua_register( L, "RL_GuiUnlock", lguiGuiUnlock );
+ /* Font. */
+ lua_register( L, "RL_GuiSetFont", lguiGuiSetFont );
+ /* Container. */
+ lua_register( L, "RL_GuiWindowBox", lguiGuiWindowBox );
+ lua_register( L, "RL_GuiPanel", lguiGuiPanel );
+ lua_register( L, "RL_GuiScrollPanel", lguiGuiScrollPanel );
+ /* Basic. */
+ lua_register( L, "RL_GuiLabel", lguiGuiLabel );
+ lua_register( L, "RL_GuiButton", lguiGuiButton );
+ lua_register( L, "RL_GuiToggle", lguiGuiToggle );
+ lua_register( L, "RL_GuiCheckBox", lguiGuiCheckBox );
+ lua_register( L, "RL_GuiTextBox", lguiGuiTextBox );
+ lua_register( L, "RL_GuiTextBoxMulti", lguiGuiTextBoxMulti );
+ lua_register( L, "RL_GuiSpinner", lguiGuiSpinner );
+ lua_register( L, "RL_GuiValueBox", lguiGuiValueBox );
+ lua_register( L, "RL_GuiSlider", lguiGuiSlider );
+ lua_register( L, "RL_GuiSliderBar", lguiGuiSliderBar );
+ lua_register( L, "RL_GuiProgressBar", lguiGuiProgressBar );
+ lua_register( L, "RL_GuiScrollBar", lguiGuiScrollBar );
+ lua_register( L, "RL_GuiDropdownBox", lguiGuiDropdownBox );
+}
+
+/* Lua util functions. */
+
+Color uluaGetColor( lua_State *L ) {
+ Color color = { 0, 0, 0, 255 };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong color value. Returning { 0, 0, 0, 255 }" );
+ return color;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ color.r = (uint8_t)lua_tointeger( L, -1 );
+ break;
+ case 1:
+ color.g = (uint8_t)lua_tointeger( L, -1 );
+ break;
+ case 2:
+ color.b = (uint8_t)lua_tointeger( L, -1 );
+ break;
+ case 3:
+ color.a = (uint8_t)lua_tointeger( L, -1 );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ return color;
+}
+
+Vector2 uluaGetVector2( lua_State *L ) {
+ Vector2 vector = { 0.0f, 0.0f };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong vector value. Returning { 0, 0 }" );
+ return vector;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ vector.x = lua_tonumber( L, -1 );
+ break;
+ case 1:
+ vector.y = lua_tonumber( L, -1 );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ return vector;
+}
+
+Vector3 uluaGetVector3( lua_State *L ) {
+ Vector3 vector = { 0.0f, 0.0f, 0.0f };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong vector value. Returning { 0, 0, 0 }" );
+ return vector;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ vector.x = lua_tonumber( L, -1 );
+ break;
+ case 1:
+ vector.y = lua_tonumber( L, -1 );
+ break;
+ case 2:
+ vector.z = lua_tonumber( L, -1 );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ return vector;
+}
+
+Rectangle uluaGetRectangle( lua_State *L ) {
+ Rectangle rect = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong rectangle value. Returning { 0, 0, 0, 0 }" );
+ return rect;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ rect.x = lua_tonumber( L, -1 );
+ break;
+ case 1:
+ rect.y = lua_tonumber( L, -1 );
+ break;
+ case 2:
+ rect.width = lua_tonumber( L, -1 );
+ break;
+ case 3:
+ rect.height = lua_tonumber( L, -1 );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ return rect;
+}
+
+Quaternion uluaGetQuaternion( lua_State *L ) {
+ Quaternion quaternion = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong quaternion value. Returning { 0, 0, 0, 0 }" );
+ return quaternion;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ quaternion.x = lua_tonumber( L, -1 );
+ break;
+ case 1:
+ quaternion.y = lua_tonumber( L, -1 );
+ break;
+ case 2:
+ quaternion.z = lua_tonumber( L, -1 );
+ break;
+ case 3:
+ quaternion.w = lua_tonumber( L, -1 );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ return quaternion;
+}
+
+Matrix uluaGetMatrix( lua_State *L ) {
+ Matrix matrix = { 0.0f };
+ float m[4][4];
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong matrix value. Returning MatrixIdentity." );
+ return MatrixIdentity();
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ int t2 = lua_gettop( L ), j = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t2 ) != 0 ) {
+ if ( lua_isnumber( L, -1 ) ) {
+ m[i][j] = lua_tonumber( L, -1 );
+ }
+ j++;
+ lua_pop( L, 1 );
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ matrix.m0 = m[0][0]; matrix.m1 = m[0][1]; matrix.m2 = m[0][2]; matrix.m3 = m[0][3];
+ matrix.m4 = m[1][0]; matrix.m5 = m[1][1]; matrix.m6 = m[1][2]; matrix.m7 = m[1][3];
+ matrix.m8 = m[2][0]; matrix.m9 = m[2][1]; matrix.m10 = m[2][2]; matrix.m11 = m[2][3];
+ matrix.m12 = m[3][0]; matrix.m13 = m[3][1]; matrix.m14 = m[3][2]; matrix.m15 = m[3][3];
+
+ return matrix;
+}
+
+BoundingBox uluaGetBoundingBox( lua_State *L ) {
+ BoundingBox box = { .min = { 0.0, 0.0, 0.0 }, .max = { 0.0, 0.0, 0.0 } };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong boundingbox value. Returning { min{ 0, 0, 0 }, max{ 0, 0, 0 } }." );
+ return box;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ box.min = uluaGetVector3( L );
+ break;
+ case 1:
+ box.max = uluaGetVector3( L );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+
+ return box;
+}
+
+Ray uluaGetRay( lua_State *L ) {
+ Ray ray = { .position = { 0.0, 0.0, 0.0 }, .direction = { 0.0, 0.0, 0.0 } };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong ray value. Returning { position{ 0, 0, 0 }, direction{ 0, 0, 0 } }." );
+ return ray;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ switch ( i ) {
+ case 0:
+ ray.position = uluaGetVector3( L );
+ break;
+ case 1:
+ ray.direction = uluaGetVector3( L );
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+
+ return ray;
+}
+
+NPatchInfo uluaGetNPatchInfo( lua_State *L ) {
+ NPatchInfo npatch = { .source = { 0.0, 0.0, 0.0, 0.0 }, .left = 0, .top = 0, .right = 0, .bottom = 0, .layout = NPATCH_NINE_PATCH };
+
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Error. Wrong ray value. Returning { source = { 0.0, 0.0, 0.0, 0.0 }, left = 0, top = 0, right = 0, bottom = 0, layout = NPATCH_NINE_PATCH }." );
+ return npatch;
+ }
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ switch ( i ) {
+ case 0:
+ npatch.source = uluaGetRectangle( L );
+ break;
+ case 1:
+ npatch.left = lua_tointeger( L, -1 );
+ break;
+ case 2:
+ npatch.top = lua_tointeger( L, -1 );
+ break;
+ case 3:
+ npatch.right = lua_tointeger( L, -1 );
+ break;
+ case 4:
+ npatch.bottom = lua_tointeger( L, -1 );
+ break;
+ case 5:
+ npatch.layout = lua_tointeger( L, -1 );
+ break;
+ default:
+ break;
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+
+ return npatch;
+}
+
+void uluaPushColor( lua_State *L, Color color ) {
+ lua_createtable( L, 3, 0 );
+ lua_pushnumber( L, color.r );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, color.g );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, color.b );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, color.a );
+ lua_rawseti( L, -2, 4 );
+}
+
+void uluaPushVector2( lua_State *L, Vector2 vector ) {
+ lua_createtable( L, 2, 0 );
+ lua_pushnumber( L, vector.x );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, vector.y );
+ lua_rawseti( L, -2, 2 );
+}
+
+void uluaPushVector3( lua_State *L, Vector3 vector ) {
+ lua_createtable( L, 3, 0 );
+ lua_pushnumber( L, vector.x );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, vector.y );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, vector.z );
+ lua_rawseti( L, -2, 3 );
+}
+
+void uluaPushRectangle( lua_State *L, Rectangle rect ) {
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, rect.x );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, rect.y );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, rect.width );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, rect.height );
+ lua_rawseti( L, -2, 4 );
+}
+
+void uluaPushMatrix( lua_State *L, Matrix matrix ) {
+ lua_createtable( L, 4, 0 );
+
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, matrix.m0 );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, matrix.m1 );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, matrix.m2 );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, matrix.m3 );
+ lua_rawseti( L, -2, 4 );
+ lua_rawseti( L, -2, 1 );
+
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, matrix.m4 );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, matrix.m5 );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, matrix.m6 );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, matrix.m7 );
+ lua_rawseti( L, -2, 4 );
+ lua_rawseti( L, -2, 2 );
+
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, matrix.m8 );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, matrix.m9 );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, matrix.m10 );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, matrix.m11 );
+ lua_rawseti( L, -2, 4 );
+ lua_rawseti( L, -2, 3 );
+
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, matrix.m12 );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, matrix.m13 );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, matrix.m14 );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, matrix.m15 );
+ lua_rawseti( L, -2, 4 );
+ lua_rawseti( L, -2, 4 );
+}
+
+void uluaPushRayCollision( lua_State *L, RayCollision rayCol ) {
+ lua_createtable( L, 4, 0 );
+ lua_pushboolean( L, rayCol.hit );
+ lua_setfield( L, -2, "hit" );
+ lua_pushnumber( L, rayCol.distance );
+ lua_setfield( L, -2, "distance" );
+ uluaPushVector3( L, rayCol.point );
+ lua_setfield( L, -2, "point" );
+ uluaPushVector3( L, rayCol.normal );
+ lua_setfield( L, -2, "normal" );
+}
+
+int uluaGetTableLen( lua_State *L ) {
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ i++;
+ lua_pop( L, 1 );
+ }
+ return i;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..e9d5db2
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,37 @@
+#include "main.h"
+#include "state.h"
+#include "lua_core.h"
+
+int main( int argn, const char **argc ) {
+ char exePath[ STRING_LEN ] = { '\0' };
+
+ if ( 1 < argn ) {
+ if ( strcmp( argc[1], "--version" ) == 0 || strcmp( argc[1], "-v" ) == 0 ) {
+ printf( "ReiLua %d.%d\n", VERSION_MAJOR, VERSION_MINOR );
+
+ return 1;
+ }
+ else{
+ sprintf( exePath, "%s/%s", GetWorkingDirectory(), argc[1] );
+ }
+ }
+ else {
+ sprintf( exePath, "%s/", GetWorkingDirectory() );
+ }
+
+ stateInit( exePath );
+
+ while ( state->run ) {
+ if ( WindowShouldClose() ) {
+ state->run = false;
+ }
+ if ( IsAudioDeviceReady() ) {
+ UpdateMusicStream( state->music );
+ }
+ luaCallProcess();
+ luaCallDraw();
+ }
+ stateFree();
+
+ return 1;
+}
diff --git a/src/models.c b/src/models.c
new file mode 100644
index 0000000..17683b8
--- /dev/null
+++ b/src/models.c
@@ -0,0 +1,2113 @@
+#include "main.h"
+#include "state.h"
+#include "models.h"
+#include "lua_core.h"
+#include "rmath.h"
+#include "textures.h"
+#include "core.h"
+
+static void checkMeshRealloc( int i ) {
+ if ( i == state->meshCount ) {
+ state->meshCount++;
+ }
+
+ if ( state->meshCount == state->meshAlloc ) {
+ state->meshAlloc += ALLOC_PAGE_SIZE;
+ state->meshes = realloc( state->meshes, state->meshAlloc * sizeof( Mesh* ) );
+
+ for ( i = state->meshCount; i < state->meshAlloc; i++ ) {
+ state->meshes[i] = NULL;
+ }
+ }
+}
+
+static void checkMaterialRealloc( int i ) {
+ if ( i == state->materialCount ) {
+ state->materialCount++;
+ }
+
+ if ( state->materialCount == state->materialAlloc ) {
+ state->materialAlloc += ALLOC_PAGE_SIZE;
+ state->materials = realloc( state->materials, state->materialAlloc * sizeof( Material* ) );
+
+ for ( i = state->materialCount; i < state->materialAlloc; i++ ) {
+ state->materials[i] = NULL;
+ }
+ }
+}
+
+static void checkModelRealloc( int i ) {
+ if ( i == state->modelCount ) {
+ state->modelCount++;
+ }
+
+ if ( state->modelCount == state->modelAlloc ) {
+ state->modelAlloc += ALLOC_PAGE_SIZE;
+ state->models = realloc( state->models, state->modelAlloc * sizeof( Model* ) );
+
+ for ( i = state->modelCount; i < state->modelAlloc; i++ ) {
+ state->models[i] = NULL;
+ }
+ }
+}
+
+static void checkAnimationRealloc( int i ) {
+ if ( i == state->animationCount ) {
+ state->animationCount++;
+ }
+
+ if ( state->animationCount == state->animationAlloc ) {
+ state->animationAlloc += ALLOC_PAGE_SIZE;
+ state->animations = realloc( state->animations, state->animationAlloc * sizeof( ModelAnimations* ) );
+
+ for ( i = state->animationCount; i < state->animationAlloc; i++ ) {
+ state->animations[i] = NULL;
+ }
+ }
+}
+
+static bool validMesh( size_t id ) {
+ if ( id < 0 || state->meshCount < id || state->meshes[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid mesh", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static bool validMaterial( size_t id ) {
+ if ( id < 0 || state->materialCount < id || state->materials[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid material", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static bool validModel( size_t id ) {
+ if ( id < 0 || state->modelCount < id || state->models[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid model", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static bool validAnimation( size_t id ) {
+ if ( id < 0 || state->animationCount < id || state->animations[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid animation", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/*
+## Models - Basic
+*/
+
+/*
+> success = RL_DrawLine3D( Vector3 startPos, Vector3 endPos, Color color )
+
+Draw a line in 3D world space
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawLine3D( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawLine3D( Vector3 startPos, Vector3 endPos, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 endPos = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 startPos = uluaGetVector3( L );
+
+ DrawLine3D( startPos, endPos, color);
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawPoint3D( Vector3 position, Color color )
+
+Draw a point in 3D space, actually a small line
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawPoint3D( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawPoint3D( Vector3 position, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+
+ DrawPoint3D( position, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCircle3D( Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color )
+
+Draw a circle in 3D world space
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCircle3D( lua_State *L ) {
+ if ( !lua_istable( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCircle3D( Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float rotationAngle = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 rotationAxis = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 center = uluaGetVector3( L );
+
+ DrawCircle3D( center, radius, rotationAxis, rotationAngle, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTriangle3D( Vector3 v1, Vector3 v2, Vector3 v3, Color color )
+
+Draw a color-filled triangle ( Vertex in counter-clockwise order! )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawTriangle3D( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTriangle3D( Vector3 v1, Vector3 v2, Vector3 v3, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 v3 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ DrawTriangle3D( v1, v2, v3, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCube( Vector3 position, Vector3 size, Color color )
+
+Draw cube
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCube( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCube( Vector3 position, Vector3 size, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 size = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 pos = uluaGetVector3( L );
+
+ DrawCubeV( pos, size, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCubeWires( Vector3 position, Vector3 size, Color color )
+
+Draw cube wires
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCubeWires( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCubeWires( Vector3 position, Vector3 size, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 size = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 pos = uluaGetVector3( L );
+
+ DrawCubeWiresV( pos, size, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCubeTexture( Texture2D texture, Vector3 position, Vector3 size, Color color )
+
+Draw cube textured
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCubeTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCubeTexture( Texture2D texture, Vector3 position, Vector3 size, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 size = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 pos = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawCubeTexture( *texturesGetSourceTexture( texId ), pos, size.x, size.y, size.z, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawSphere( Vector3 centerPos, float radius, Color color )
+
+Draw sphere
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawSphere( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawSphere( Vector3 centerPos, float radius, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 centerPos = uluaGetVector3( L );
+
+ DrawSphere( centerPos, radius, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawSphereEx( Vector3 centerPos, float radius, int rings, int slices, Color color )
+
+Draw sphere with extended parameters
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawSphereEx( lua_State *L ) {
+ if ( !lua_istable( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawSphereEx( Vector3 centerPos, float radius, int rings, int slices, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int slices = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int rings = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 centerPos = uluaGetVector3( L );
+
+ DrawSphereEx( centerPos, radius, rings, slices, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawSphereWires( Vector3 centerPos, float radius, int rings, int slices, Color color )
+
+Draw sphere wires
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawSphereWires( lua_State *L ) {
+ if ( !lua_istable( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawSphereWires( Vector3 centerPos, float radius, int rings, int slices, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int slices = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int rings = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 centerPos = uluaGetVector3( L );
+
+ DrawSphereWires( centerPos, radius, rings, slices, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCylinder( Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color )
+
+Draw a cylinder/cone
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCylinder( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCylinder( Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int slices = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float height = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float radiusBottom = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float radiusTop = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+
+ DrawCylinder( position, radiusTop, radiusBottom, height, slices, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCylinderEx( Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color )
+
+Draw a cylinder with base at startPos and top at endPos
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCylinderEx( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_istable( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCylinderEx( Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int sides = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float endRadius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float startRadius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 endPos = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 startPos = uluaGetVector3( L );
+
+ DrawCylinderEx( startPos, endPos, startRadius, endRadius, sides, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCylinderWires( Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color )
+
+Draw a cylinder/cone wires
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCylinderWires( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCylinderWires( Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int slices = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float height = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float radiusBottom = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float radiusTop = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+
+ DrawCylinderWires( position, radiusTop, radiusBottom, height, slices, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCylinderWiresEx( Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color )
+
+Draw a cylinder wires with base at startPos and top at endPos
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawCylinderWiresEx( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_istable( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCylinderWiresEx( Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int sides = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ float endRadius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float startRadius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 endPos = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 startPos = uluaGetVector3( L );
+
+ DrawCylinderWiresEx( startPos, endPos, startRadius, endRadius, sides, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawPlane( Vector3 centerPos, Vector2 size, Color color )
+
+Draw a plane XZ
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawPlane( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawPlane( Vector3 centerPos, Vector2 size, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 size = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector3 centerPos = uluaGetVector3( L );
+
+ DrawPlane( centerPos, size, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawQuad3DTexture( texture, Vector3{} vertices, Vector2{} texCoords, Color color )
+
+Draw 3D quad texture using vertices and texture coordinates. Texture coordinates opengl style 0.0 - 1.0.
+Note! Could be replaced something like "DrawPlaneTextureRec"
+
+- Failure return false
+- Success return true
+*/
+int lmodelDrawQuad3DTexture( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawQuad3DTexture( texture, Vector3{} vertices, Vector2{} texCoords, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+
+ /* TexCoords. */
+ Vector2 texcoords[4] = { 0 };
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) && i < 4 ) {
+ texcoords[i] = uluaGetVector2( L );
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+
+ /* Vertices. */
+ Vector3 vertices[4] = { 0 };
+
+ t = lua_gettop( L );
+ i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) && i < 4 ) {
+ vertices[i] = uluaGetVector3( L );
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ // Draw.
+ rlCheckRenderBatchLimit( 4 );
+ rlSetTexture( texturesGetSourceTexture( texId )->id );
+
+ //TODO Normals. maybe something like Vector3Normalize(Vector3CrossProduct(Vector3Subtract(vB, vA), Vector3Subtract(vC, vA)));
+
+ rlBegin( RL_QUADS );
+ rlColor4ub( color.r, color.g, color.b, color.a );
+
+ for ( i = 0; i < 4; ++i ) {
+ rlTexCoord2f( texcoords[i].x, texcoords[i].y );
+ rlVertex3f( vertices[i].x, vertices[i].y, vertices[i].z );
+ }
+ rlEnd();
+ rlSetTexture( 0 );
+
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawRay( Ray ray, Color color )
+
+Draw a ray line
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawRay( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawRay( Ray ray, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ DrawRay( ray, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawGrid( int slices, float spacing )
+
+Draw a grid ( Centered at ( 0, 0, 0 ) )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawGrid( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawGrid( int slices, float spacing )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ DrawGrid( lua_tointeger( L, -2 ), lua_tonumber( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Models - Mesh
+*/
+
+/*
+> mesh = RL_GenMeshPoly( int sides, float radius )
+
+Generate polygonal mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshPoly( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshPoly( int sides, float radius )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ float radius = lua_tonumber( L, -1 );
+ int sides = lua_tointeger( L, -2 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshPoly( sides, radius );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshPlane( float width, float length, int resX, int resZ )
+
+Generate plane mesh ( With subdivisions )
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshPlane( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshPlane( float width, float length, int resX, int resZ )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int resZ = lua_tointeger( L, -1 );
+ int resX = lua_tointeger( L, -2 );
+ float length = lua_tonumber( L, -3 );
+ float width = lua_tonumber( L, -4 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshPlane( width, length, resX, resZ );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshCube( Vector3 size )
+
+Generate cuboid mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshCube( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshCube( Vector3 size )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ Vector3 size = uluaGetVector3( L );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshCube( size.x, size.y, size.z );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshSphere( float radius, int rings, int slices )
+
+Generate sphere mesh ( Standard sphere )
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshSphere( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshSphere( float radius, int rings, int slices )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int slices = lua_tointeger( L, -1 );
+ int rings = lua_tointeger( L, -2 );
+ float radius = lua_tonumber( L, -3 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshSphere( radius, rings, slices );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshCylinder( float radius, float height, int slices )
+
+Generate cylinder mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshCylinder( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshCylinder( float radius, float height, int slices )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int slices = lua_tointeger( L, -1 );
+ float height = lua_tonumber( L, -2 );
+ float radius = lua_tonumber( L, -3 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshCylinder( radius, height, slices);
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshCone( float radius, float height, int slices )
+
+Generate cone/pyramid mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshCone( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshCone( float radius, float height, int slices )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int slices = lua_tointeger( L, -1 );
+ float height = lua_tonumber( L, -2 );
+ float radius = lua_tonumber( L, -3 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshCone( radius, height, slices);
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshTorus( float radius, float size, int radSeg, int sides )
+
+Generate torus mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshTorus( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshTorus( float radius, float size, int radSeg, int sides )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int sides = lua_tointeger( L, -1 );
+ int radSeg = lua_tointeger( L, -2 );
+ float size = lua_tonumber( L, -3 );
+ float radius = lua_tonumber( L, -4 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshTorus( radius, size, radSeg, sides );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshKnot( float radius, float size, int radSeg, int sides )
+
+Generate torus mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshKnot( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshKnot( float radius, float size, int radSeg, int sides )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int sides = lua_tointeger( L, -1 );
+ int radSeg = lua_tointeger( L, -2 );
+ float size = lua_tonumber( L, -3 );
+ float radius = lua_tonumber( L, -4 );
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshKnot( radius, size, radSeg, sides );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshHeightmap( Image heightmap, Vector3 size )
+
+Generate heightmap mesh from image data
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshHeightmap( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshHeightmap( Image heightmap, Vector3 size )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ Vector3 size = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Image *heightmap = state->images[ lua_tointeger( L, -1 ) ];
+ int i = 0;
+
+ for ( i = 0; i < state->meshCount; i++ ) {
+ if ( state->meshes[i] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[i] = malloc( sizeof( Mesh ) );
+ *state->meshes[i] = GenMeshHeightmap( *heightmap, size );
+ lua_pushinteger( L, i );
+ checkMeshRealloc( i );
+
+ return 1;
+}
+
+/*
+> mesh = RL_GenMeshCustom( Vector3{} vertices, Vector2{} texCoords, Vector3{} normals )
+
+Generate custom mesh
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsGenMeshCustom( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenMeshCustom( Vector3{} vertices, Vector2{} texCoords, Vector3{} normals )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ Mesh mesh = { 0 };
+ size_t len = uluaGetTableLen( L );
+
+ mesh.vertexCount = len * 3;
+ mesh.triangleCount = len;
+
+ mesh.vertices = (float*)MemAlloc( mesh.vertexCount * 3 * sizeof(float) );
+ mesh.texcoords = (float*)MemAlloc( mesh.vertexCount * 2 * sizeof(float) );
+ mesh.normals = (float*)MemAlloc( mesh.vertexCount * 3 * sizeof(float) );
+ mesh.colors = (unsigned char*)MemAlloc( mesh.vertexCount * 4 * sizeof(unsigned char) );
+
+ /* Normals. */
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ Vector3 vec = uluaGetVector3( L );
+ mesh.normals[(i*3)+0] = vec.x;
+ mesh.normals[(i*3)+1] = vec.y;
+ mesh.normals[(i*3)+2] = vec.z;
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+
+ /* TexCoords. */
+
+ t = lua_gettop( L );
+ i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ Vector2 vec = uluaGetVector2( L );
+ mesh.texcoords[(i*2)+0] = vec.x;
+ mesh.texcoords[(i*2)+1] = vec.y;
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+
+ /* Vertices. */
+
+ t = lua_gettop( L );
+ i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ Vector3 vec = uluaGetVector3( L );
+ mesh.vertices[(i*3)+0] = vec.x;
+ mesh.vertices[(i*3)+1] = vec.y;
+ mesh.vertices[(i*3)+2] = vec.z;
+
+ mesh.colors[(i*4)+0] = (unsigned char)255;
+ mesh.colors[(i*4)+1] = (unsigned char)255;
+ mesh.colors[(i*4)+2] = (unsigned char)255;
+ mesh.colors[(i*4)+3] = (unsigned char)255;
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+
+ UploadMesh( &mesh, false );
+
+ int j = 0;
+
+ for ( j = 0; j < state->meshCount; j++ ) {
+ if ( state->meshes[j] == NULL ) {
+ break;
+ }
+ }
+ state->meshes[j] = malloc( sizeof( Mesh ) );
+ *state->meshes[j] = mesh;
+ lua_pushinteger( L, j );
+ checkMeshRealloc( j );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadMesh( Mesh mesh )
+
+Unload mesh data from CPU and GPU
+
+- Failure return false
+- Success return true
+*/
+int lmodelsUnloadMesh( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadMesh( Mesh mesh )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validMesh( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadMesh( *state->meshes[ id ] );
+ state->meshes[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawMesh( Mesh mesh, Material material, Matrix transform )
+
+Draw a 3d mesh with material and transform
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawMesh( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawMesh( Mesh mesh, Material material, Matrix transform )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix matrix = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ size_t materialId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t meshId = lua_tointeger( L, -1 );
+
+ if ( !validMesh( meshId ) || !validMaterial( materialId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawMesh( *state->meshes[ meshId ], *state->materials[ materialId ], matrix );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/* TODO Needs shader to work. Test it when we have shaders. */
+/*
+> success = RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances )
+
+Draw multiple mesh instances with material and different transforms
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawMeshInstanced( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawMeshInstanced( Mesh mesh, Material material, Matrix{} transforms, int instances )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int instances = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Matrix matrises[ instances ];
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( lua_istable( L, -1 ) ) {
+ matrises[i] = uluaGetMatrix( L );
+ }
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+ size_t materialId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t meshId = lua_tointeger( L, -1 );
+
+ if ( !validMesh( meshId ) || !validMaterial( materialId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ DrawMeshInstanced( *state->meshes[ meshId ], *state->materials[ materialId ], matrises, instances );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetMeshColor( Mesh mesh, Color color )
+
+Updades mesh color vertex attribute buffer
+NOTE: Currently only works on custom mesh
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetMeshColor( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMeshColor( Mesh mesh, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ size_t meshId = lua_tointeger( L, -1 );
+
+ if ( !validMesh( meshId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ Mesh *mesh = state->meshes[ meshId ];
+
+ if ( mesh->colors == NULL ) {
+ TraceLog( LOG_WARNING, "Mesh %d %s", meshId, "Mesh doesn't have vertex colors allocated" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ for ( int i = 0; i < mesh->vertexCount; ++i ) {
+ mesh->colors[(i*4)+0] = (unsigned char)color.r;
+ mesh->colors[(i*4)+1] = (unsigned char)color.g;
+ mesh->colors[(i*4)+2] = (unsigned char)color.b;
+ mesh->colors[(i*4)+3] = (unsigned char)color.a;
+ }
+ /* Update vertex attribute: color */
+ rlUpdateVertexBuffer( mesh->vboId[3], mesh->colors, mesh->vertexCount * 4 * sizeof( unsigned char ), 0 );
+
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Models - Material
+*/
+
+/*
+> material = RL_LoadMaterialDefault()
+
+Load default material
+
+- Success return int
+*/
+int lmodelsLoadMaterialDefault( lua_State *L ) {
+ int i = 0;
+
+ for ( i = 0; i < state->materialCount; i++ ) {
+ if ( state->materials[i] == NULL ) {
+ break;
+ }
+ }
+ state->materials[i] = malloc( sizeof( Material ) );
+ *state->materials[i] = LoadMaterialDefault();
+ lua_pushinteger( L, i );
+ checkMaterialRealloc( i );
+
+ return 1;
+}
+
+/*
+> material = RL_CreateMaterial( material{} )
+
+Load material from table. See material table definition
+
+- Failure return false
+- Success return int
+*/
+int lmodelsCreateMaterial( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CreateMaterial( material{} )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->materialCount; i++ ) {
+ if ( state->materials[i] == NULL ) {
+ break;
+ }
+ }
+ state->materials[i] = malloc( sizeof( Material ) );
+ *state->materials[i] = LoadMaterialDefault();
+
+ int t = lua_gettop( L );
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ if ( strcmp( "maps", (char*)lua_tostring( L, -2 ) ) == 0 && lua_istable( L, -1 ) ) {
+ int t2 = lua_gettop( L );
+ lua_pushnil( L );
+
+ while ( lua_next( L, t2 ) != 0 ) {
+ /* Loop maps. Array where we don't care about the index value. */
+ if ( lua_istable( L, -1 ) ) {
+ int t3 = lua_gettop( L ), j = 0, map = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t3 ) != 0 ) {
+ switch ( j ) {
+ case 0: /* Map */
+ map = lua_tointeger( L, -1 );
+ break;
+ case 1: /* Parameters */
+ {
+ int t4 = lua_gettop( L );
+ lua_pushnil( L );
+
+ while ( lua_next( L, t4 ) != 0 ) {
+ if ( strcmp( "texture", (char*)lua_tostring( L, -2 ) ) == 0 && lua_isnumber( L, -1 ) ) {
+ state->materials[i]->maps[map].texture = *state->textures[ lua_tointeger( L, -1 ) ];
+ }
+ else if ( strcmp( "color", (char*)lua_tostring( L, -2 ) ) == 0 && lua_istable( L, -1 ) ) {
+ state->materials[i]->maps[map].color = uluaGetColor( L );
+ }
+ else if ( strcmp( "value", (char*)lua_tostring( L, -2 ) ) == 0 && lua_isnumber( L, -1 ) ) {
+ state->materials[i]->maps[map].value = lua_tonumber( L, -1 );
+ }
+ lua_pop( L, 1 );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ j++;
+ lua_pop( L, 1 );
+ }
+ }
+ lua_pop( L, 1 );
+ }
+ }
+ else if ( strcmp( "params", (char*)lua_tostring( L, -2 ) ) == 0 && lua_istable( L, -1 ) ) {
+ int t2 = lua_gettop( L ), j = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t2 ) != 0 ) {
+ if ( j <= 3 ) {
+ state->materials[i]->params[j] = lua_tonumber( L, -1 );
+ }
+ j++;
+ lua_pop( L, 1 );
+ }
+ }
+ else if ( strcmp( "shader", (char*)lua_tostring( L, -2 ) ) == 0 && lua_isnumber( L, -1 ) ) {
+ /* TODO Shader when implemented. */
+ }
+ lua_pop( L, 1 );
+ }
+ lua_pushinteger( L, i );
+ checkMaterialRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadMaterial( Material material )
+
+Unload material from GPU memory ( VRAM )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsUnloadMaterial( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadMaterial( Material material )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validMaterial( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadMaterial( *state->materials[ id ] );
+ state->materials[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetMaterialTexture( Material material, int mapType, Texture2D texture )
+
+Set texture for a material map type ( MATERIAL_MAP_ALBEDO, MATERIAL_MAP_METALNESS... )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetMaterialTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMaterialTexture( Material material, int mapType, Texture2D texture )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -1 );
+ size_t materialId = lua_tointeger( L, -3 );
+
+ if ( !validMaterial( materialId ) || !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ // SetMaterialTexture( state->materials[ lua_tointeger( L, -3 ) ], lua_tointeger( L, -2 ), *state->textures[ lua_tointeger( L, -1 ) ] );
+ SetMaterialTexture( state->materials[ materialId ], lua_tointeger( L, -2 ), *texturesGetSourceTexture( texId ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetMaterialColor( Material material, int mapType, Color color )
+
+Set color for a material map type
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetMaterialColor( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMaterialColor( Material material, int mapType, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ size_t mapType = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t materialId = lua_tointeger( L, -1 );
+
+ if ( !validMaterial( materialId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->materials[ materialId ]->maps[ mapType ].color = color;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetMaterialValue( Material material, int mapType, float value )
+
+Set value for a material map type
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetMaterialValue( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetMaterialValue( Material material, int mapType, float value )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float value = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ size_t mapType = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t materialId = lua_tointeger( L, -1 );
+
+ if ( !validMaterial( materialId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->materials[ materialId ]->maps[ mapType ].value = value;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Models - Model
+*/
+
+/*
+> model = RL_LoadModel( string fileName )
+
+Load model from files ( Meshes and materials )
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsLoadModel( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadModel( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->modelCount; i++ ) {
+ if ( state->models[i] == NULL ) {
+ break;
+ }
+ }
+ state->models[i] = malloc( sizeof( Model ) );
+ *state->models[i] = LoadModel( lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkModelRealloc( i );
+
+ return 1;
+}
+
+/*
+> model = RL_LoadModelFromMesh( Mesh mesh )
+
+Load model from generated mesh ( Default material )
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsLoadModelFromMesh( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadModelFromMesh( Mesh mesh )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ size_t meshId = lua_tointeger( L, -1 );
+
+ if ( !validMesh( meshId ) ) {
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->modelCount; i++ ) {
+ if ( state->models[i] == NULL ) {
+ break;
+ }
+ }
+ state->models[i] = malloc( sizeof( Model ) );
+ *state->models[i] = LoadModelFromMesh( *state->meshes[ meshId ] );
+ lua_pushinteger( L, i );
+ checkModelRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadModel( Model model )
+
+Unload model ( Including meshes ) from memory ( RAM and/or VRAM )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsUnloadModel( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadModel( Model model )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t modelId = lua_tointeger( L, -1 );
+
+ if ( !validModel( modelId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadModel( *state->models[ modelId ] );
+ state->models[ modelId ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawModel( Model model, Vector3 position, float scale, Color tint )
+
+Draw a model ( With texture if set )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawModel( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawModel( Model model, Vector3 position, float scale, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float scale = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ size_t modelId = lua_tointeger( L, -1 );
+
+ if ( !validModel( modelId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawModel( *state->models[ modelId ], position, scale, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawModelEx( Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint )
+
+Draw a model with extended parameters
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawModelEx( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_istable( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawModelEx( Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector3 scale = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ float rotationAngle = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 rotationAxis = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ size_t modelId = lua_tointeger( L, -1 );
+
+ if ( !validModel( modelId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawModelEx( *state->models[ modelId ], position, rotationAxis, rotationAngle, scale, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetModelMaterial( Model model, Material modelMaterial, Material material )
+
+Copies material to model material. ( Model material is the material id in models. Material can be deleted if not used elsewhere )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetModelMaterial( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetModelMaterial( Model model, Material modelMaterial, Material material )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t materialId = lua_tointeger( L, -1 );
+ size_t modelId = lua_tointeger( L, -3 );
+
+ if ( !validModel( modelId ) || !validMaterial( materialId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ Model *model = state->models[ modelId ];
+ int modelMaterialId = lua_tointeger( L, -2 );
+ Material *material = state->materials[ materialId ];
+
+ /* Copy material data instead of using pointer. Pointer would result in double free error. */
+ model->materials[ modelMaterialId ].shader = material->shader;
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_DIFFUSE ] = material->maps[ MATERIAL_MAP_DIFFUSE ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_METALNESS ] = material->maps[ MATERIAL_MAP_METALNESS ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_NORMAL ] = material->maps[ MATERIAL_MAP_NORMAL ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_ROUGHNESS ] = material->maps[ MATERIAL_MAP_ROUGHNESS ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_OCCLUSION ] = material->maps[ MATERIAL_MAP_OCCLUSION ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_EMISSION ] = material->maps[ MATERIAL_MAP_EMISSION ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_HEIGHT ] = material->maps[ MATERIAL_MAP_HEIGHT ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_CUBEMAP ] = material->maps[ MATERIAL_MAP_CUBEMAP ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_IRRADIANCE ] = material->maps[ MATERIAL_MAP_IRRADIANCE ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_PREFILTER ] = material->maps[ MATERIAL_MAP_PREFILTER ];
+ model->materials[ modelMaterialId ].maps[ MATERIAL_MAP_BRDF ] = material->maps[ MATERIAL_MAP_BRDF ];
+
+ for ( int i = 0; i < 4; i++ ) {
+ model->materials[ modelMaterialId ].params[i] = material->params[i];
+ }
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetModelMaterial( Model model, Material modelMaterial, Material material )
+
+Set material for a mesh ( Mesh and material on this model )
+
+- Failure return false
+- Success return true
+*/
+int lmodelsSetModelMeshMaterial( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetModelMeshMaterial( Model model, int meshId, int materialId )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int materialId = lua_tointeger( L, -1 );
+ int meshId = lua_tointeger( L, -2 );
+ size_t modelId = lua_tointeger( L, -3 );
+
+ if ( !validModel( modelId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetModelMeshMaterial( state->models[ modelId ], meshId, materialId );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawBillboard( Camera camera, Texture2D texture, Vector3 position, float size, Color tint )
+
+Draw a billboard texture
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawBillboard( lua_State *L ) {
+ if ( !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_istable( L, -3 )
+ || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawBillboard( Camera camera, Texture2D texture, Vector3 position, float size, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float size = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) || !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ DrawBillboard( *state->camera3Ds[ cameraId ], *texturesGetSourceTexture( texId ), position, size, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawBillboardRec( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint )
+
+Draw a billboard texture defined by source
+
+- Failure return false
+- Success return true
+*/
+int lmodelsDrawBillboardRec( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_isnumber( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawBillboardRec( Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 size = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector3 position = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Rectangle source = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t cameraId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) || !validCamera3D( cameraId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ DrawBillboardRec( *state->camera3Ds[ cameraId ], *texturesGetSourceTexture( texId ), source, position, size, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Model - Animations
+*/
+
+/*
+> animations, animationCount = RL_LoadModelAnimations( string fileName )
+
+Load model animations from file
+
+- Failure return -1
+- Success return int, int
+*/
+int lmodelsLoadModelAnimations( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadModelAnimations( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->animationCount; i++ ) {
+ if ( state->animations[i] == NULL ) {
+ break;
+ }
+ }
+ state->animations[i] = malloc( sizeof( ModelAnimations ) );
+ state->animations[i]->animations = LoadModelAnimations( lua_tostring( L, -1 ), &state->animations[i]->animCount );
+ checkAnimationRealloc( i );
+
+ lua_pushinteger( L, i );
+ lua_pushinteger( L, state->animations[i]->animCount );
+
+ return 2;
+}
+
+/*
+> success = RL_UpdateModelAnimation( Model model, ModelAnimations animations, int animation, int frame )
+
+Update model animation pose
+
+- Failure return false
+- Success return true
+*/
+int lmodelsUpdateModelAnimation( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UpdateModelAnimation( Model model, ModelAnimations animations, int animation, int frame )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int frame = imax( 0, lua_tointeger( L, -1 ) );
+ size_t animId = lua_tointeger( L, -3 );
+ size_t modelId = lua_tointeger( L, -4 );
+
+ if ( !validModel( modelId ) || !validAnimation( animId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ UpdateModelAnimation( *state->models[ modelId ], state->animations[ animId ]->animations[ lua_tointeger( L, -2 ) ], frame );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> boneCount = RL_GetModelAnimationBoneCount( ModelAnimations animations, int animation )
+
+Return modelAnimation bone count
+
+- Failure return false
+- Success return int
+*/
+int lmodelsGetModelAnimationBoneCount( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetModelAnimationBoneCount( ModelAnimations animations, int animation )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t animId = lua_tointeger( L, -2 );
+
+ if ( !validAnimation( animId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushinteger( L, state->animations[ animId ]->animations[ lua_tointeger( L, -1 ) ].boneCount );
+
+ return 1;
+}
+
+/*
+> frameCount = RL_GetModelAnimationFrameCount( ModelAnimations animations, int animation )
+
+Return modelAnimation frame count
+
+- Failure return false
+- Success return int
+*/
+int lmodelsGetModelAnimationFrameCount( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetModelAnimationFrameCount( ModelAnimations animations, int animation )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t animId = lua_tointeger( L, -2 );
+
+ if ( !validAnimation( animId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ lua_pushinteger( L, state->animations[ animId ]->animations[ lua_tointeger( L, -1 ) ].frameCount );
+
+ return 1;
+}
+
+/*
+## Model - Collision
+*/
+
+/*
+> collision = RL_CheckCollisionSpheres( Vector3 center1, float radius1, Vector3 center2, float radius2 )
+
+Check collision between two spheres
+
+- Failure return nil
+- Success return bool
+*/
+int lmodelsCheckCollisionSpheres( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionSpheres( Vector3 center1, float radius1, Vector3 center2, float radius2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float radius2 = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 center2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ float radius1 = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 center1 = uluaGetVector3( L );
+
+ lua_pushboolean( L, CheckCollisionSpheres( center1, radius1, center2, radius2 ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionBoxes( BoundingBox box1, BoundingBox box2 )
+
+Check collision between two bounding boxes
+
+- Failure return nil
+- Success return bool
+*/
+int lmodelsCheckCollisionBoxes( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionBoxes( BoundingBox box1, BoundingBox box2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ BoundingBox box2 = uluaGetBoundingBox( L );
+ lua_pop( L, 1 );
+ BoundingBox box1 = uluaGetBoundingBox( L );
+
+ lua_pushboolean( L, CheckCollisionBoxes( box1, box2 ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionBoxSphere( BoundingBox box, Vector3 center, float radius )
+
+Check collision between box and sphere
+
+- Failure return nil
+- Success return bool
+*/
+int lmodelsCheckCollisionBoxSphere( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionBoxSphere( BoundingBox box, Vector3 center, float radius )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 center = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ BoundingBox box = uluaGetBoundingBox( L );
+
+ lua_pushboolean( L, CheckCollisionBoxSphere( box, center, radius ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionSphere( Ray ray, Vector3 center, float radius )
+
+Get collision info between ray and sphere. ( RayCollision is Lua table of { hit, distance, point, normal } )
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionSphere( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionSphere( Ray ray, Vector3 center, float radius )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 center = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ uluaPushRayCollision( L, GetRayCollisionSphere( ray, center, radius ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionBox( Ray ray, BoundingBox box )
+
+Get collision info between ray and box
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionBox( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionBox( Ray ray, BoundingBox box )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ BoundingBox box = uluaGetBoundingBox( L );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ uluaPushRayCollision( L, GetRayCollisionBox( ray, box ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionModel( Ray ray, Model model )
+
+Get collision info between ray and model
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionModel( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionModel( Ray ray, Model model )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t modelId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ if ( !validModel( modelId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+ uluaPushRayCollision( L, GetRayCollisionModel( ray, *state->models[ modelId ] ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionMesh( Ray ray, Mesh mesh, Matrix transform )
+
+Get collision info between ray and mesh
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionMesh( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionMesh( Ray ray, Mesh mesh, Matrix transform )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Matrix transform = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ size_t meshId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ if ( !validMesh( meshId ) ) {
+ lua_pushnil( L );
+ return 1;
+ }
+ uluaPushRayCollision( L, GetRayCollisionMesh( ray, *state->meshes[ meshId ], transform ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionTriangle( Ray ray, Vector3 p1, Vector3 p2, Vector3 p3 )
+
+Get collision info between ray and triangle
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionTriangle( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionTriangle( Ray ray, Vector3 p1, Vector3 p2, Vector3 p3 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector3 p3 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 p2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 p1 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ uluaPushRayCollision( L, GetRayCollisionTriangle( ray, p1, p2, p3 ) );
+
+ return 1;
+}
+
+/*
+> rayCollision = RL_GetRayCollisionQuad( Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4 )
+
+Get collision info between ray and quad
+
+- Failure return nil
+- Success return RayCollision
+*/
+int lmodelsGetRayCollisionQuad( lua_State *L ) {
+ if ( !lua_istable( L, -5 ) || !lua_istable( L, -4 ) || !lua_istable( L, -3 )
+ || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetRayCollisionQuad( Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector3 p4 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 p3 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 p2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 p1 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Ray ray = uluaGetRay( L );
+
+ uluaPushRayCollision( L, GetRayCollisionQuad( ray, p1, p2, p3, p4 ) );
+
+ return 1;
+}
+
diff --git a/src/rgui.c b/src/rgui.c
new file mode 100644
index 0000000..2a967da
--- /dev/null
+++ b/src/rgui.c
@@ -0,0 +1,544 @@
+#include "main.h"
+#include "state.h"
+#include "rgui.h"
+#include "lua_core.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "raygui.h"
+
+/*
+## Gui - Global
+*/
+
+/*
+> RL_GuiEnable()
+
+Enable gui controls ( Global state )
+*/
+int lguiGuiEnable( lua_State *L ) {
+ GuiEnable();
+
+ return 1;
+}
+
+/*
+> RL_GuiDisable()
+
+Disable gui controls ( Global state )
+*/
+int lguiGuiDisable( lua_State *L ) {
+ GuiDisable();
+
+ return 1;
+}
+
+/*
+> RL_GuiLock()
+
+Lock gui controls ( Global state )
+*/
+int lguiGuiLock( lua_State *L ) {
+ GuiLock();
+
+ return 1;
+}
+
+/*
+> RL_GuiUnlock()
+
+Unlock gui controls ( Global state )
+*/
+int lguiGuiUnlock( lua_State *L ) {
+ GuiUnlock();
+
+ return 1;
+}
+
+/*
+## Gui - Font
+*/
+
+/*
+> success = RL_GuiSetFont( Font font )
+
+Set gui custom font ( Global state )
+
+- Failure return false
+- Success return true
+*/
+int lguiGuiSetFont( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiSetFont( Font font )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ GuiSetFont( *state->fonts[ lua_tointeger( L, -1 ) ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Gui - Container
+*/
+
+/*
+> state = RL_GuiWindowBox( Rectangle bounds, string title )
+
+Window Box control, shows a window that can be closed
+
+- Failure return nil
+- Success return bool
+*/
+int lguiGuiWindowBox( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiWindowBox( Rectangle bounds, string title )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiWindowBox( rect, text ) );
+
+ return 1;
+}
+
+/*
+> success = RL_GuiPanel( Rectangle bounds )
+
+Panel control, useful to group controls
+
+- Failure return false
+- Success return true
+*/
+int lguiGuiPanel( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiPanel( Rectangle bounds )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Rectangle rect = uluaGetRectangle( L );
+
+ GuiPanel( rect );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> view, scroll = RL_GuiScrollPanel( Rectangle bounds, Rectangle content, Vector2 scroll )
+
+Scroll Panel control
+
+- Failure return false
+- Success return Rectangle, Vector2
+*/
+int lguiGuiScrollPanel( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiScrollPanel( Rectangle bounds, Rectangle content, Vector2 scroll )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 scroll = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle content = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle bounds = uluaGetRectangle( L );
+
+ uluaPushRectangle( L, GuiScrollPanel( bounds, content, &scroll ) );
+ uluaPushVector2( L, scroll );
+
+ return 2;
+}
+
+/*
+## Gui - Basic
+*/
+
+/*
+> success = RL_GuiLabel( Rectangle bounds, string text )
+
+Label control, shows text
+
+- Failure return false
+- Success return true
+*/
+int lguiGuiLabel( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiLabel( Rectangle bounds, string text )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ GuiLabel( rect, text );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> clicked = RL_GuiButton( Rectangle bounds, string text )
+
+Button control, returns true when clicked
+
+- Failure return nil
+- Success return boolean
+*/
+int lguiGuiButton( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiButton( Rectangle bounds, string text )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiButton( rect, text ) );
+
+ return 1;
+}
+
+/*
+> active = RL_GuiToggle( Rectangle bounds, string text, bool active )
+
+Toggle Button control, returns true when active
+
+- Failure return nil
+- Success return boolean
+*/
+int lguiGuiToggle( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isstring( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiToggle( Rectangle bounds, string text, bool active )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool checked = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiToggle( rect, text, checked ) );
+
+ return 1;
+}
+
+/*
+> active = RL_GuiCheckBox( Rectangle bounds, string text, bool checked )
+
+Check Box control, returns true when active
+
+- Failure return nil
+- Success return boolean
+*/
+int lguiGuiCheckBox( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isstring( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiCheckBox( Rectangle bounds, string text, bool checked )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool checked = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiCheckBox( rect, text, checked ) );
+
+ return 1;
+}
+
+/*
+> pressed, text = RL_GuiTextBox( Rectangle bounds, string text, int textSize, bool editMode )
+
+Text Box control, updates input text
+
+- Failure return nil
+- Success return boolean, string
+*/
+int lguiGuiTextBox( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isstring( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiTextBox( Rectangle bounds, string text, int textSize, bool editMode )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool editMode = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ int textSize = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiTextBox( rect, text, textSize, editMode ) );
+ lua_pushstring( L, text );
+
+ return 2;
+}
+
+/*
+> pressed, text = RL_GuiTextBoxMulti( Rectangle bounds, string text, int textSize, bool editMode )
+
+Text Box control with multiple lines
+
+- Failure return nil
+- Success return boolean, string
+*/
+int lguiGuiTextBoxMulti( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isstring( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiTextBoxMulti( Rectangle bounds, string text, int textSize, bool editMode )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool editMode = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ int textSize = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiTextBoxMulti( rect, text, textSize, editMode ) );
+ lua_pushstring( L, text );
+
+ return 2;
+}
+
+/*
+> pressed, value = RL_GuiSpinner( Rectangle bounds, string text, int value, int minValue, int maxValue, bool editMode )
+
+Spinner control, returns selected value
+
+- Failure return nil
+- Success return boolean, int
+*/
+int lguiGuiSpinner( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isstring( L, -5 ) || !lua_isnumber( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiSpinner( Rectangle bounds, string text, int value, int minValue, int maxValue, bool editMode )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool editMode = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ int maxValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int minValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int value = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiSpinner( rect, text, &value, minValue, maxValue, editMode ) );
+ lua_pushinteger( L, value );
+
+ return 2;
+}
+
+/*
+> pressed, value = RL_GuiValueBox( Rectangle bounds, string text, int value, int minValue, int maxValue, bool editMode )
+
+Value Box control, updates input text with numbers
+
+- Failure return nil
+- Success return boolean, int
+*/
+int lguiGuiValueBox( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isstring( L, -5 ) || !lua_isnumber( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiValueBox( Rectangle bounds, string text, int value, int minValue, int maxValue, bool editMode )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool editMode = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ int maxValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int minValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int value = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiValueBox( rect, text, &value, minValue, maxValue, editMode ) );
+ lua_pushinteger( L, value );
+
+ return 2;
+}
+
+/*
+> value = RL_GuiSlider( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )
+
+Slider control, returns selected value
+
+- Failure return nil
+- Success return float
+*/
+int lguiGuiSlider( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isstring( L, -5 ) || !lua_isstring( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiSlider( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float maxValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float minValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float value = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ char textRight[ STRING_LEN ] = { '\0' };
+ strcpy( textRight, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ char textLeft[ STRING_LEN ] = { '\0' };
+ strcpy( textLeft, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushnumber( L, GuiSlider( rect, textLeft, textRight, value, minValue, maxValue ) );
+
+ return 1;
+}
+
+/*
+> value = RL_GuiSliderBar( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )
+
+Slider Bar control, returns selected value
+
+- Failure return nil
+- Success return float
+*/
+int lguiGuiSliderBar( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isstring( L, -5 ) || !lua_isstring( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiSliderBar( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float maxValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float minValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float value = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ char textRight[ STRING_LEN ] = { '\0' };
+ strcpy( textRight, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ char textLeft[ STRING_LEN ] = { '\0' };
+ strcpy( textLeft, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushnumber( L, GuiSliderBar( rect, textLeft, textRight, value, minValue, maxValue ) );
+
+ return 1;
+}
+
+/*
+> value = RL_GuiProgressBar( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )
+
+Progress Bar control, shows current progress value
+
+- Failure return nil
+- Success return float
+*/
+int lguiGuiProgressBar( lua_State *L ) {
+ if ( !lua_istable( L, -6 ) || !lua_isstring( L, -5 ) || !lua_isstring( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiProgressBar( Rectangle bounds, string textLeft, string textRight, float value, float minValue, float maxValue )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float maxValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float minValue = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float value = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ char textRight[ STRING_LEN ] = { '\0' };
+ strcpy( textRight, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ char textLeft[ STRING_LEN ] = { '\0' };
+ strcpy( textLeft, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushnumber( L, GuiProgressBar( rect, textLeft, textRight, value, minValue, maxValue ) );
+
+ return 1;
+}
+
+/*
+> value = RL_GuiScrollBar( Rectangle bounds, int value, int minValue, int maxValue )
+
+Scroll Bar control
+
+- Failure return nil
+- Success return int
+*/
+int lguiGuiScrollBar( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiScrollBar( Rectangle bounds, int value, int minValue, int maxValue )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ int maxValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int minValue = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int value = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushinteger( L, GuiScrollBar( rect, value, minValue, maxValue ) );
+
+ return 1;
+}
+
+/*
+> pressed, item = RL_GuiDropdownBox( Rectangle bounds, string text, int active, bool editMode )
+
+Dropdown Box control, returns selected item
+
+- Failure return nil
+- Success return bool, int
+*/
+int lguiGuiDropdownBox( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isstring( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isboolean( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GuiDropdownBox( Rectangle bounds, string text, int active, bool editMode )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ bool editMode = lua_toboolean( L, -1 );
+ lua_pop( L, 1 );
+ int active = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ char text[ STRING_LEN ] = { '\0' };
+ strcpy( text, lua_tostring( L, -1 ) );
+ lua_pop( L, 1 );
+ Rectangle rect = uluaGetRectangle( L );
+
+ lua_pushboolean( L, GuiDropdownBox( rect, text, &active, editMode ) );
+ lua_pushinteger( L, active );
+
+ return 2;
+}
diff --git a/src/rmath.c b/src/rmath.c
new file mode 100644
index 0000000..7ad9bdb
--- /dev/null
+++ b/src/rmath.c
@@ -0,0 +1,978 @@
+#include "main.h"
+#include "state.h"
+#include "rmath.h"
+#include "lua_core.h"
+
+inline int imin( int a, int b ) {
+ return a < b ? a : b;
+}
+
+inline int imax( int a, int b ) {
+ return a > b ? a : b;
+}
+
+/*
+## Math - Vector2
+*/
+
+/*
+> result = RL_Vector2Add( Vector2 v1, Vector2 v2 )
+
+Add two vectors (v1 + v2)
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Add( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Add( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Add( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Subtract( Vector2 v1, Vector2 v2 )
+
+Subtract two vectors (v1 - v2)
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Subtract( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Subtract( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Subtract( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Multiply( Vector2 v1, Vector2 v2 )
+
+Multiply vector by vector
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Multiply( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Multiply( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Multiply( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Length( vector2 vector )
+
+Calculate vector length
+
+- Failure return false
+- Success return float
+*/
+int lmathVector2Length( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Length( vector2 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v = uluaGetVector2( L );
+
+ lua_pushnumber( L, Vector2Length( v ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2DotProduct( Vector2 v1, Vector2 v2 )
+
+Calculate two vectors dot product
+
+- Failure return false
+- Success return float
+*/
+int lmathVector2DotProduct( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2DotProduct( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ lua_pushnumber( L, Vector2DotProduct( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Distance( Vector2 v1, Vector2 v2 )
+
+Calculate distance between two vectors
+
+- Failure return false
+- Success return float
+*/
+int lmathVector2Distance( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Distance( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ lua_pushnumber( L, Vector2Distance( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Angle( Vector2 v1, Vector2 v2 )
+
+Calculate angle from two vectors
+
+- Failure return false
+- Success return float
+*/
+int lmathVector2Angle( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Angle( Vector2 v1, Vector2 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ lua_pushnumber( L, Vector2Angle( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Normalize( Vector2 v )
+
+Normalize provided vector
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Normalize( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Normalize( Vector2 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v = Vector2Normalize( uluaGetVector2( L ) );
+
+ uluaPushVector2( L, v );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Lerp( Vector2 v1, Vector2 v2, float amount )
+
+Calculate linear interpolation between two vectors
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Lerp( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Lerp( Vector2 v1, Vector2 v2, float amount )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float amount = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Lerp( v1, v2, amount ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Reflect( Vector2 v, Vector2 normal )
+
+Calculate reflected vector to normal
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Reflect( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Reflect( Vector2 v, Vector2 normal )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Reflect( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2Rotate( Vector2 v, float angle )
+
+Rotate vector by angle
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2Rotate( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2Rotate( Vector2 v, float angle )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float degs = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 v = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2Rotate( v, degs ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector2MoveTowards( Vector2 v, Vector2 target, float maxDistance )
+
+Move Vector towards target
+
+- Failure return false
+- Success return Vector2
+*/
+int lmathVector2MoveTowards( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector2MoveTowards( Vector2 v, Vector2 target, float maxDistance )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float maxDistance = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ uluaPushVector2( L, Vector2MoveTowards( v1, v2, maxDistance ) );
+
+ return 1;
+}
+
+/*
+## Math - Vector 3
+*/
+
+/*
+> result = RL_Vector3CrossProduct( Vector3 v1, Vector3 v2 )
+
+Add two vectors
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Add( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Add( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Add( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Subtract( Vector3 v1, Vector3 v2 )
+
+Subtract two vectors
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Subtract( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Subtract( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Subtract( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Subtract( Vector3 v1, Vector3 v2 )
+
+Multiply vector by vector
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Multiply( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Multiply( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Multiply( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3CrossProduct( Vector3 v1, Vector3 v2 )
+
+Calculate two vectors cross product
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3CrossProduct( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3CrossProduct( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3CrossProduct( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Perpendicular( Vector3 v )
+
+Calculate one vector perpendicular vector
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Perpendicular( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Perpendicular( Vector3 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Perpendicular( v ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Length( Vector3 v )
+
+Calculate one vector perpendicular vector
+
+- Failure return false
+- Success return float
+*/
+int lmathVector3Length( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Length( Vector3 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ lua_pushnumber( L, Vector3Length( v ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3LengthSqr( Vector3 v )
+
+Calculate vector square length
+
+- Failure return false
+- Success return float
+*/
+int lmathVector3LengthSqr( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3LengthSqr( Vector3 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ lua_pushnumber( L, Vector3LengthSqr( v ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3DotProduct( Vector3 v1, Vector3 v2 )
+
+Calculate two vectors dot product
+
+- Failure return false
+- Success return float
+*/
+int lmathVector3DotProduct( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3DotProduct( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ lua_pushnumber( L, Vector3DotProduct( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Distance( Vector3 v1, Vector3 v2 )
+
+Calculate distance between two vectors
+
+- Failure return false
+- Success return float
+*/
+int lmathVector3Distance( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Distance( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ lua_pushnumber( L, Vector3Distance( v1, v2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Normalize( Vector3 v )
+
+Normalize provided vector
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Normalize( lua_State *L ) {
+ /* Vector. */
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Normalize( Vector3 v )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Normalize( v ) );
+
+ return 1;
+}
+
+/*
+> v1, v2 = RL_Vector3OrthoNormalize( Vector3 v1, Vector3 v2 )
+
+Orthonormalize provided vectors. Makes vectors normalized and orthogonal to each other.
+Gram-Schmidt function implementation
+
+- Failure return false
+- Success return Vector3, Vector3
+*/
+int lmathVector3OrthoNormalize( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3OrthoNormalize( Vector3 v1, Vector3 v2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ Vector3OrthoNormalize( &v1, &v2 );
+
+ uluaPushVector3( L, v1 );
+ uluaPushVector3( L, v2 );
+
+ return 2;
+}
+
+/*
+> result = RL_Vector3Transform( Vector3 v, Matrix mat )
+
+Transforms a Vector3 by a given Matrix
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Transform( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Transform( Vector3 v, Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v1 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Matrix mat = uluaGetMatrix( L );
+
+ uluaPushVector3( L, Vector3Transform( v1, mat ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3RotateByQuaternion( Vector3 v, Quaternion q )
+
+Transform a vector by quaternion rotation
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3RotateByQuaternion( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3RotateByQuaternion( Vector3 v, Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v1 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushVector3( L, Vector3RotateByQuaternion( v1, q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Lerp( Vector3 v1, Vector3 v2, float amount )
+
+Calculate linear interpolation between two vectors
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Lerp( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Lerp( Vector3 v1, Vector3 v2, float amount )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float amount = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 v2 = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Lerp( v1, v2, amount ) );
+
+ return 1;
+}
+
+/*
+> result = RL_Vector3Reflect( Vector3 v, Vector3 normal )
+
+Calculate reflected vector to normal
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathVector3Reflect( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_Vector3Reflect( Vector3 v, Vector3 normal )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 normal = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 v1 = uluaGetVector3( L );
+
+ uluaPushVector3( L, Vector3Reflect( v1, normal ) );
+
+ return 1;
+}
+
+/*
+## Math - Matrix
+*/
+
+/*
+> result = RL_MatrixDeterminant( Matrix mat )
+
+Compute matrix determinant
+
+- Failure return false
+- Success return float
+*/
+int lmathMatrixDeterminant( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixDeterminant( Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+
+ lua_pushnumber( L, MatrixDeterminant( mat ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixTranspose( Matrix mat )
+
+Transposes provided matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixTranspose( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixTranspose( Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixTranspose( mat ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixInvert( Matrix mat )
+
+Invert provided matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixInvert( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixInvert( Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixInvert( mat ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixNormalize( Matrix mat )
+
+Normalize provided matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixNormalize( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixNormalize( Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixNormalize( mat ) );
+
+ return 1;
+}
+
+/*
+> result = MatrixIdentity()
+
+Get identity matrix
+
+- Success return Matrix
+*/
+int lmathMatrixIdentity( lua_State *L ) {
+ uluaPushMatrix( L, MatrixIdentity() );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixAdd( Matrix left, Matrix right )
+
+Add two matrices
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixAdd( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixAdd( Matrix left, Matrix right )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat2 = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ Matrix mat1 = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixAdd( mat1, mat2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixAdd( Matrix left, Matrix right )
+
+Subtract two matrices (left - right)
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixSubtract( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixSubtract( Matrix left, Matrix right )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat2 = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ Matrix mat1 = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixSubtract( mat1, mat2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixMultiply( Matrix left, Matrix right )
+
+Get two matrix multiplication
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixMultiply( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixMultiply( Matrix left, Matrix right )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat2 = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ Matrix mat1 = uluaGetMatrix( L );
+
+ uluaPushMatrix( L, MatrixMultiply( mat1, mat2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixTranslate( Vector3 translate )
+
+Get translation matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixTranslate( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixTranslate( Vector3 translate )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ uluaPushMatrix( L, MatrixTranslate( v.x, v.y, v.z ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixRotate( Vector3 axis, float angle )
+
+Create rotation matrix from axis and angle. NOTE: Angle should be provided in radians
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixRotate( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixRotate( Vector3 axis, float angle )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float angle = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 axis = uluaGetVector3( L );
+
+ uluaPushMatrix( L, MatrixRotate( axis, angle ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixScale( Vector3 scale )
+
+Get scaling matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixScale( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixScale( Vector3 scale )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 v = uluaGetVector3( L );
+
+ uluaPushMatrix( L, MatrixScale( v.x, v.y, v.z ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixFrustum( double left, double right, double bottom, double top, double near, double far )
+
+Get perspective projection matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixFrustum( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixFrustum( double left, double right, double bottom, double top, double near, double far )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float far = lua_tonumber( L, -1 );
+ float near = lua_tonumber( L, -2 );
+ float top = lua_tonumber( L, -3 );
+ float bottom = lua_tonumber( L, -4 );
+ float right = lua_tonumber( L, -5 );
+ float left = lua_tonumber( L, -6 );
+
+ uluaPushMatrix( L, MatrixFrustum( left, right, bottom, top, near, far ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixPerspective( double fovy, double aspect, double near, double far )
+
+Get perspective projection matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixPerspective( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixPerspective( double fovy, double aspect, double near, double far )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float far = lua_tonumber( L, -1 );
+ float near = lua_tonumber( L, -2 );
+ float aspect = lua_tonumber( L, -3 );
+ float fovy = lua_tonumber( L, -4 );
+
+ uluaPushMatrix( L, MatrixPerspective( fovy, aspect, near, far ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixOrtho( double left, double right, double bottom, double top, double near, double far )
+
+Get orthographic projection matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixOrtho( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixOrtho( double left, double right, double bottom, double top, double near, double far )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float far = lua_tonumber( L, -1 );
+ float near = lua_tonumber( L, -2 );
+ float top = lua_tonumber( L, -3 );
+ float bottom = lua_tonumber( L, -4 );
+ float right = lua_tonumber( L, -5 );
+ float left = lua_tonumber( L, -6 );
+
+ uluaPushMatrix( L, MatrixOrtho( left, right, bottom, top, near, far ) );
+
+ return 1;
+}
+
+/*
+> result = RL_MatrixLookAt( Vector3 eye, Vector3 target, Vector3 up )
+
+Get camera look-at matrix ( View matrix )
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathMatrixLookAt( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_MatrixLookAt( Vector3 eye, Vector3 target, Vector3 up )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 up = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 target = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 eye = uluaGetVector3( L );
+
+ uluaPushMatrix( L, MatrixLookAt( eye, target, up ) );
+
+ return 1;
+}
diff --git a/src/shapes.c b/src/shapes.c
new file mode 100644
index 0000000..cb489f0
--- /dev/null
+++ b/src/shapes.c
@@ -0,0 +1,457 @@
+#include "main.h"
+#include "shapes.h"
+#include "lua_core.h"
+
+/*
+## Shapes - Drawing
+*/
+
+/*
+> success = RL_DrawPixel( Vector2 pos, Color color )
+
+Draw a pixel
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawPixel( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawPixel( Vector2 pos, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 pos = uluaGetVector2( L );
+
+ DrawPixelV( pos, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawLine( Vector2 startPos, Vector2 endPos, float thickness, Color color )
+
+Draw a line defining thickness
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawLine( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawLine( Vector2 startPos, Vector2 endPos, float thickness, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float thickness = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 endPos = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 startPos = uluaGetVector2( L );
+
+ DrawLineEx( startPos, endPos, thickness, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCircle( Vector2 center, float radius, Color color )
+
+Draw a color-filled circle
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawCircle( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCircle( Vector2 center, float radius, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+
+ DrawCircleV( center, radius, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawCircleLines( Vector2 center, float radius, Color color )
+
+Draw circle outline
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawCircleLines( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawCircleLines( Vector2 center, float radius, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+
+ DrawCircleLines( center.x, center.y, radius, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawRectangle( Rectangle rec, Color color )
+
+Draw a color-filled rectangle
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawRectangle( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawRectangle( Rectangle rec, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Rectangle rect = { 0, 0, 0, 0 };
+ Color color = { 0, 0, 0, 0 };
+
+ color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ rect = uluaGetRectangle( L );
+
+ DrawRectangleRec( rect, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawRectanglePro( Rectangle rec, Vector2 origin, float rotation, Color color )
+
+Draw a color-filled rectangle with pro parameters
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawRectanglePro( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawRectanglePro( Rectangle rec, Vector2 origin, float rotation, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float rotation = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 origin = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle rec = uluaGetRectangle( L );
+
+ DrawRectanglePro( rec, origin, rotation, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTriangle( Vector2 v1, Vector2 v2, Vector2 v3, Color color )
+
+Draw a color-filled triangle ( Vertex in counter-clockwise order! )
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawTriangle( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTriangle( Vector2 v1, Vector2 v2, Vector2 v3, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 v3 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ DrawTriangle( v1, v2, v3, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTriangleLines( Vector2 v1, Vector2 v2, Vector2 v3, Color color )
+
+Draw triangle outline ( Vertex in counter-clockwise order! )
+
+- Failure return false
+- Success return true
+*/
+int lshapesDrawTriangleLines( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTriangleLines( Vector2 v1, Vector2 v2, Vector2 v3, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 v3 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 v1 = uluaGetVector2( L );
+
+ DrawTriangleLines( v1, v2, v3, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Shapes - Collision
+*/
+
+/*
+> collision = RL_CheckCollisionRecs( Rectangle rec1, Rectangle rec2 )
+
+Check collision between two rectangles
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionRecs( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionRecs( Rectangle rec1, Rectangle rec2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Rectangle rect1 = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle rect2 = uluaGetRectangle( L );
+
+ lua_pushboolean( L, CheckCollisionRecs( rect1, rect2 ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionCircles( Vector2 center1, float radius1, Vector2 center2, float radius2 )
+
+Check collision between two circles
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionCircles( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionCircles( Vector2 center1, float radius1, Vector2 center2, float radius2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float radius2 = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ float radius1 = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center1 = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionCircles( center1, radius1, center2, radius2 ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionCircleRec( Vector2 center, float radius, Rectangle rec )
+
+Check collision between circle and rectangle
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionCircleRec( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionCircleRec( Vector2 center, float radius, Rectangle rec )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Rectangle rec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionCircleRec( center, radius, rec ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionPointRec( Vector2 point, Rectangle rec )
+
+Check if point is inside rectangle
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionPointRec( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionPointRec( Vector2 point, Rectangle rec )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Rectangle rec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Vector2 point = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionPointRec( point, rec ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionPointCircle( Vector2 point, Vector2 center, float radius )
+
+Check if point is inside circle
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionPointCircle( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionPointCircle( Vector2 point, Vector2 center, float radius )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ float radius = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 point = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionPointCircle( point, center, radius ) );
+
+ return 1;
+}
+
+/*
+> collision = RL_CheckCollisionPointTriangle( Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3 )
+
+Check if point is inside a triangle
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionPointTriangle( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionPointTriangle( Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector2 p3 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 p2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 p1 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 point = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionPointTriangle( point, p1, p2, p3 ) );
+
+ return 1;
+}
+
+/*
+> collision, position = RL_CheckCollisionLines( Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2 )
+
+Check the collision between two lines defined by two points each, returns collision point by reference
+
+- Failure return nil
+- Success return bool, Vector2
+*/
+int lshapesCheckCollisionLines( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionLines( Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Vector2 endPos2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 startPos2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 endPos1 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 startPos1 = uluaGetVector2( L );
+
+ Vector2 colPoint = { 0, 0 };
+
+ lua_pushboolean( L, CheckCollisionLines( startPos1, endPos1, startPos2, endPos2, &colPoint ) );
+ uluaPushVector2( L, colPoint );
+
+ return 2;
+}
+
+/*
+> collision = RL_CheckCollisionPointLine( Vector2 point, Vector2 p1, Vector2 p2, int threshold )
+
+Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
+
+- Failure return nil
+- Success return bool
+*/
+int lshapesCheckCollisionPointLine( lua_State *L ) {
+ if ( !lua_istable( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_CheckCollisionPointLine( Vector2 point, Vector2 p1, Vector2 p2, int threshold )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ int threshold = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 p2 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 p1 = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 point = uluaGetVector2( L );
+
+ lua_pushboolean( L, CheckCollisionPointLine( point, p1, p2, threshold ) );
+
+ return 1;
+}
+
+/*
+> rectangle = RL_GetCollisionRec( Rectangle rec1, Rectangle rec2 )
+
+Get collision rectangle for two rectangles collision
+
+- Failure return nil
+- Success return Rectangle
+*/
+int lshapesGetCollisionRec( lua_State *L ) {
+ /* Rectangle rec1, Rectangle rec2 */
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetCollisionRec( Rectangle rec1, Rectangle rec2 )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ Rectangle rec2 = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle rec1 = uluaGetRectangle( L );
+
+ uluaPushRectangle( L, GetCollisionRec( rec1, rec2 ) );
+
+ return 1;
+}
diff --git a/src/state.c b/src/state.c
new file mode 100644
index 0000000..d9b2ad4
--- /dev/null
+++ b/src/state.c
@@ -0,0 +1,194 @@
+#include "main.h"
+#include "state.h"
+#include "lua_core.h"
+#include "textures.h"
+
+State *state;
+
+bool stateInit( const char *exePath ) {
+ state = malloc( sizeof( State ) );
+
+ state->exePath = malloc( STRING_LEN * sizeof( char ) );
+ strncpy( state->exePath, exePath, STRING_LEN - 1 );
+
+ state->hasWindow = true;
+ state->run = true;
+ state->resolution = (Vector2){ 1024, 720 };
+ state->luaState = NULL;
+ state->targetFPS = 60;
+ state->textureSource = TEXTURE_SOURCE_TEXTURE;
+ /* Images. */
+ state->imageAlloc = ALLOC_PAGE_SIZE;
+ state->imageCount = 0;
+ state->images = malloc( state->imageAlloc * sizeof( Image* ) );
+ /* Textures. */
+ state->textureAlloc = ALLOC_PAGE_SIZE;
+ state->textureCount = 0;
+ state->textures = malloc( state->textureAlloc * sizeof( Texture2D* ) );
+ /* RenderTextures. */
+ state->renderTextureAlloc = ALLOC_PAGE_SIZE;
+ state->renderTextureCount = 0;
+ state->renderTextures = malloc( state->renderTextureAlloc * sizeof( RenderTexture2D* ) );
+ /* Fonts. */
+ state->fontAlloc = ALLOC_PAGE_SIZE;
+ state->fontCount = 1;
+ state->fonts = malloc( state->fontAlloc * sizeof( Font* ) );
+ /* Sounds. */
+ state->soundAlloc = ALLOC_PAGE_SIZE;
+ state->soundCount = 0;
+ state->sounds = malloc( state->soundAlloc * sizeof( Sound* ) );
+ /* Camera3D's. */
+ state->camera3DAlloc = ALLOC_PAGE_SIZE;
+ state->camera3DCount = 0;
+ state->camera3Ds = malloc( state->camera3DAlloc * sizeof( Camera3D* ) );
+ /* Meshes. */
+ state->meshAlloc = ALLOC_PAGE_SIZE;
+ state->meshCount = 0;
+ state->meshes = malloc( state->meshAlloc * sizeof( Mesh* ) );
+ /* Materials. */
+ state->materialAlloc = ALLOC_PAGE_SIZE;
+ state->materialCount = 1;
+ state->materials = malloc( state->materialAlloc * sizeof( Material* ) );
+ /* Models. */
+ state->modelAlloc = ALLOC_PAGE_SIZE;
+ state->modelCount = 0;
+ state->models = malloc( state->modelAlloc * sizeof( Model* ) );
+ /* ModelsAnimations. */
+ state->animationAlloc = ALLOC_PAGE_SIZE;
+ state->animationCount = 0;
+ state->animations = malloc( state->animationAlloc * sizeof( ModelAnimations* ) );
+ /* Shaders. */
+ state->shaderAlloc = ALLOC_PAGE_SIZE;
+ state->shaderCount = 0;
+ state->shaders = malloc( state->shaderAlloc * sizeof( Shader* ) );
+
+ for ( int i = 0; i < ALLOC_PAGE_SIZE; i++ ) {
+ state->images[i] = NULL;
+ state->textures[i] = NULL;
+ state->renderTextures[i] = NULL;
+ state->sounds[i] = NULL;
+ state->camera3Ds[i] = NULL;
+ state->meshes[i] = NULL;
+ state->models[i] = NULL;
+ state->animations[i] = NULL;
+ state->shaders[i] = NULL;
+
+ /* The ones we want to save the first. */
+ if ( 0 < i ) {
+ state->fonts[i] = NULL;
+ state->materials[i] = NULL;
+ }
+ }
+
+ InitWindow( state->resolution.x, state->resolution.y, "ReiLua" );
+ /* Has to be after InitWindod where opengl context is created. */
+ state->materials[0] = malloc( sizeof( Material ) );
+ *state->materials[0] = LoadMaterialDefault();
+ state->fonts[0] = malloc( sizeof( Font ) );
+ *state->fonts[0] = GetFontDefault();
+
+ if ( !IsWindowReady() ) {
+ state->hasWindow = false;
+ state->run = false;
+ }
+ else {
+ SetTargetFPS( state->targetFPS );
+ }
+
+ InitAudioDevice();
+ state->run = luaInit();
+
+ return state->run;
+}
+
+void stateFree() {
+ for ( int i = 0; i < state->imageCount; ++i ) {
+ if ( state->images[i] != NULL ) {
+ UnloadImage( *state->images[i] );
+ free( state->images[i] );
+ }
+ }
+ for ( int i = 0; i < state->textureCount; ++i ) {
+ if ( state->textures[i] != NULL ) {
+ UnloadTexture( *state->textures[i] );
+ free( state->textures[i] );
+ }
+ }
+ for ( int i = 0; i < state->renderTextureCount; ++i ) {
+ if ( state->renderTextures[i] != NULL ) {
+ UnloadRenderTexture( *state->renderTextures[i] );
+ free( state->renderTextures[i] );
+ }
+ }
+ for ( int i = 0; i < state->fontCount; ++i ) {
+ if ( state->fonts[i] != NULL ) {
+ UnloadFont( *state->fonts[i] );
+ free( state->fonts[i] );
+ }
+ }
+ for ( int i = 0; i < state->soundCount; ++i ) {
+ if ( state->sounds[i] != NULL ) {
+ UnloadSound( *state->sounds[i] );
+ free( state->sounds[i] );
+ }
+ }
+ for ( int i = 0; i < state->camera3DCount; ++i ) {
+ if ( state->camera3Ds[i] != NULL ) {
+ free( state->camera3Ds[i] );
+ }
+ }
+ for ( int i = 0; i < state->modelCount; ++i ) {
+ if ( state->models[i] != NULL ) {
+ // UnloadModel( *state->models[i] );
+ UnloadModelKeepMeshes( *state->models[i] );
+ free( state->models[i] );
+ }
+ }
+ for ( int i = 0; i < state->meshCount; ++i ) {
+ if ( state->meshes[i] != NULL ) {
+ UnloadMesh( *state->meshes[i] );
+ free( state->meshes[i] );
+ }
+ }
+ for ( int i = 0; i < state->materialCount; ++i ) {
+ if ( state->materials[i] != NULL ) {
+ UnloadMaterial( *state->materials[i] );
+ free( state->materials[i] );
+ }
+ }
+ for ( int i = 0; i < state->animationCount; ++i ) {
+ if ( state->animations[i] != NULL ) {
+ UnloadModelAnimations( state->animations[i]->animations, state->animations[i]->animCount );
+ free( state->animations[i] );
+ }
+ }
+ for ( int i = 0; i < state->shaderCount; ++i ) {
+ if ( state->shaders[i] != NULL ) {
+ UnloadShader( *state->shaders[i] );
+ free( state->shaders[i] );
+ }
+ }
+
+ if ( IsAudioDeviceReady() ) {
+ CloseAudioDevice();
+ UnloadMusicStream( state->music );
+ }
+ if ( state->hasWindow ) {
+ CloseWindow();
+ }
+ if ( state->luaState != NULL ) {
+ lua_close( state->luaState );
+ }
+ free( state->images );
+ free( state->textures );
+ free( state->renderTextures );
+ free( state->fonts );
+ free( state->sounds );
+ free( state->camera3Ds );
+ free( state->meshes );
+ free( state->materials );
+ free( state->models );
+ free( state->animations );
+ free( state->shaders );
+ free( state );
+}
diff --git a/src/text.c b/src/text.c
new file mode 100644
index 0000000..0637971
--- /dev/null
+++ b/src/text.c
@@ -0,0 +1,102 @@
+#include "main.h"
+#include "state.h"
+#include "text.h"
+#include "lua_core.h"
+
+static void checkFontRealloc( int i ) {
+ if ( i == state->fontCount ) {
+ state->fontCount++;
+ }
+
+ if ( state->fontCount == state->fontAlloc ) {
+ state->fontAlloc += ALLOC_PAGE_SIZE;
+ state->fonts = realloc( state->fonts, state->fontAlloc * sizeof( Font* ) );
+
+ for ( i = state->fontCount; i < state->fontAlloc; i++ ) {
+ state->fonts[i] = NULL;
+ }
+ }
+}
+
+bool validFont( size_t id ) {
+ if ( id < 0 || state->fontCount < id || state->fonts[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid font", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/*
+## Text - Loading
+*/
+
+/*
+> font = RL_LoadFont( string fileName )
+
+Load font from file into GPU memory ( VRAM )
+
+- Failure return -1
+- Success return int
+*/
+int lmodelsLoadFont( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadFont( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ int i = 0;
+
+ for ( i = 0; i < state->fontCount; i++ ) {
+ if ( state->fonts[i] == NULL ) {
+ break;
+ }
+ }
+ state->fonts[i] = malloc( sizeof( Font ) );
+ *state->fonts[i] = LoadFont( lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkFontRealloc( i );
+
+ return 1;
+}
+
+/*
+## Text - Draw
+*/
+
+/*
+> success = RL_DrawText( Font font, string text, Vector2 position, float fontSize, float spacing, Color tint )
+
+Draw text using font and additional parameters
+
+- Failure return false
+- Success return true
+*/
+int ltextDrawText( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_isstring( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawText( Font font, string text, Vector2 position, float fontSize, float spacing, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float spacing = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float fontSize = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 position = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t fontId = lua_tointeger( L, -2 );
+
+ if ( !validFont( fontId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTextEx( *state->fonts[ fontId ], lua_tostring( L, -1 ), position, fontSize, spacing, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
diff --git a/src/textures.c b/src/textures.c
new file mode 100644
index 0000000..b147fff
--- /dev/null
+++ b/src/textures.c
@@ -0,0 +1,1057 @@
+#include "main.h"
+#include "state.h"
+#include "textures.h"
+#include "text.h"
+#include "lua_core.h"
+
+static void checkImageRealloc( int i ) {
+ if ( i == state->imageCount ) {
+ state->imageCount++;
+ }
+
+ if ( state->imageCount == state->imageAlloc ) {
+ state->imageAlloc += ALLOC_PAGE_SIZE;
+ state->images = realloc( state->images, state->imageAlloc * sizeof( Image* ) );
+
+ for ( i = state->imageCount; i < state->imageAlloc; i++ ) {
+ state->images[i] = NULL;
+ }
+ }
+}
+
+static void checkTextureRealloc( int i ) {
+ if ( i == state->textureCount ) {
+ state->textureCount++;
+ }
+
+ if ( state->textureCount == state->textureAlloc ) {
+ state->textureAlloc += ALLOC_PAGE_SIZE;
+ state->textures = realloc( state->textures, state->textureAlloc * sizeof( Texture2D* ) );
+
+ for ( i = state->textureCount; i < state->textureAlloc; i++ ) {
+ state->textures[i] = NULL;
+ }
+ }
+}
+
+static void checkRenderTextureRealloc( int i ) {
+ if ( i == state->renderTextureCount ) {
+ state->renderTextureCount++;
+ }
+
+ if ( state->renderTextureCount == state->renderTextureAlloc ) {
+ state->renderTextureAlloc += ALLOC_PAGE_SIZE;
+ state->renderTextures = realloc( state->renderTextures, state->renderTextureAlloc * sizeof( RenderTexture2D* ) );
+
+ for ( i = state->renderTextureCount; i < state->renderTextureAlloc; i++ ) {
+ state->renderTextures[i] = NULL;
+ }
+ }
+}
+
+bool validImage( size_t id ) {
+ if ( id < 0 || state->imageCount < id || state->images[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid image", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+bool validTexture( size_t id ) {
+ if ( id < 0 || state->textureCount < id || state->textures[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid texture", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+bool validRenderTexture( size_t id ) {
+ if ( id < 0 || state->renderTextureCount < id || state->renderTextures[ id ] == NULL ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid renderTexture", id );
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+bool validSourceTexture( size_t id ) {
+ switch ( state->textureSource ) {
+ case TEXTURE_SOURCE_TEXTURE:
+ return validTexture( id );
+ case TEXTURE_SOURCE_RENDER_TEXTURE:
+ return validRenderTexture( id );
+ default:
+ return validTexture( id );
+ break;
+ }
+}
+
+Texture2D* texturesGetSourceTexture( size_t index ) {
+ switch ( state->textureSource ) {
+ case TEXTURE_SOURCE_TEXTURE:
+ return state->textures[ index ];
+ case TEXTURE_SOURCE_RENDER_TEXTURE:
+ return &state->renderTextures[ index ]->texture;
+ default:
+ return state->textures[ index ];
+ break;
+ }
+}
+
+/*
+## Textures - Load
+*/
+
+/*
+> image = RL_LoadImage( string fileName )
+
+Load image from file into CPU memory ( RAM )
+
+- Failure return -1
+- Success return int
+*/
+int ltexturesLoadImage( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadImage( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+
+ if ( FileExists( lua_tostring( L, -1 ) ) ) {
+ int i = 0;
+
+ for ( i = 0; i < state->imageCount; i++ ) {
+ if ( state->images[i] == NULL ) {
+ break;
+ }
+ }
+ state->images[i] = malloc( sizeof( Image ) );
+ *state->images[i] = LoadImage( lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkImageRealloc( i );
+ return 1;
+ }
+ else {
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+}
+
+/*
+> image = RL_GenImageColor( int width, int height, Color color )
+
+Generate image: plain color
+
+- Failure return -1
+- Success return int
+*/
+int ltexturesGenImageColor( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenImageColor( int width, int height, Color color )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int height = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ int width = lua_tointeger( L, -1 );
+ int i = 0;
+
+ for ( i = 0; i < state->imageCount; i++ ) {
+ if ( state->images[i] == NULL ) {
+ break;
+ }
+ }
+ state->images[i] = malloc( sizeof( Image ) );
+ *state->images[i] = GenImageColor( width, height, color );
+ lua_pushinteger( L, i );
+ checkImageRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadImage( Image image )
+
+Unload image from CPU memory ( RAM )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesUnloadImage( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadImage( Image image )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validImage( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadImage( *state->images[ id ] );
+ state->images[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> texture = RL_LoadTexture( string fileName )
+
+Load texture from file into GPU memory ( VRAM )
+
+- Failure return -1
+- Success return int
+*/
+int ltexturesLoadTexture( lua_State *L ) {
+ if ( !lua_isstring( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadTexture( string fileName )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+
+ if ( FileExists( lua_tostring( L, -1 ) ) ) {
+ int i = 0;
+
+ for ( i = 0; i < state->textureCount; i++ ) {
+ if ( state->textures[i] == NULL ) {
+ break;
+ }
+ }
+ state->textures[i] = malloc( sizeof( Texture2D ) );
+ *state->textures[i] = LoadTexture( lua_tostring( L, -1 ) );
+ lua_pushinteger( L, i );
+ checkTextureRealloc( i );
+ return 1;
+ }
+ else {
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+}
+
+/*
+> texture = RL_LoadTextureFromImage( Image image )
+
+Load texture from image data
+
+- Failure return -1
+- Success return int
+*/
+int ltexturesLoadTextureFromImage( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadTextureFromImage( Image image )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ int i = 0;
+
+ for ( i = 0; i < state->textureCount; i++ ) {
+ if ( state->textures[i] == NULL ) {
+ break;
+ }
+ }
+ state->textures[i] = malloc( sizeof( Texture2D ) );
+ *state->textures[i] = LoadTextureFromImage( *state->images[ imageId ] );
+ lua_pushinteger( L, i );
+ checkTextureRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadTexture( Texture2D texture )
+
+Unload texture from GPU memory ( VRAM )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesUnloadTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadTexture( Texture2D texture )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validTexture( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadTexture( *state->textures[ id ] );
+ state->textures[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> renderTexture = RL_LoadRenderTexture( Vector2 size )
+
+Load texture for rendering ( framebuffer )
+
+- Failure return -1
+- Success return int
+*/
+int ltexturesLoadRenderTexture( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_LoadRenderTexture( Vector2 size )" );
+ lua_pushinteger( L, -1 );
+ return 1;
+ }
+ Vector2 size = uluaGetVector2( L );
+ int i = 0;
+
+ for ( i = 0; i < state->renderTextureCount; i++ ) {
+ if ( state->renderTextures[i] == NULL ) {
+ break;
+ }
+ }
+ state->renderTextures[i] = malloc( sizeof( RenderTexture2D ) );
+ *state->renderTextures[i] = LoadRenderTexture( (int)size.x, (int)size.y );
+ lua_pushinteger( L, i );
+ checkRenderTextureRealloc( i );
+
+ return 1;
+}
+
+/*
+> success = RL_UnloadRenderTexture( RenderTexture2D target )
+
+Unload render texture from GPU memory ( VRAM )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesUnloadRenderTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_UnloadRenderTexture( RenderTexture2D target )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t id = lua_tointeger( L, -1 );
+
+ if ( !validRenderTexture( id ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ UnloadRenderTexture( *state->renderTextures[ id ] );
+ state->renderTextures[ id ] = NULL;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Textures - Image Drawing
+*/
+
+/*
+> success = RL_ImageClearBackground( Image dst, Color color )
+
+Clear image background with given color
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageClearBackground( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageClearBackground( Image dst, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageClearBackground( state->images[ imageId ], color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDrawPixel( Image dst, Vector2 position, Color color )
+
+Draw pixel within an image
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawPixel( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDrawPixel( Image dst, Vector2 position, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 position = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawPixelV( state->images[ imageId ], position, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDrawLine( Image dst, Vector2 start, Vector2 end, Color color )
+
+Draw line within an image
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawLine( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDrawLine( Image dst, Vector2 start, Vector2 end, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 end = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Vector2 start = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawLineV( state->images[ imageId ], start, end, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDrawCircle( Image dst, Vector2 center, int radius, Color color )
+
+Draw circle within an image
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawCircle( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDrawCircle( Image dst, Vector2 center, int radius, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int radius = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawCircleV( state->images[ imageId ], center, radius, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDrawRectangle( Image dst, Rectangle rec, Color color )
+
+Draw rectangle within an image
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawRectangle( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDrawRectangle( Image dst, Rectangle rec, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Rectangle rec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawRectangleRec( state->images[ imageId ], rec, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawRectangleLines( Image dst, Rectangle rec, int thick, Color color )
+
+Draw rectangle lines within an image
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawRectangleLines( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawRectangleLines( Image dst, Rectangle rec, int thick, Color color )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int thick = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Rectangle rec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t imageId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawRectangleLines( state->images[ imageId ], rec, thick, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDraw( Image dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint )
+
+Draw a source image within a destination image ( Tint applied to source )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDraw( lua_State *L ) {
+ if ( !lua_isnumber( L, -5 ) || !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDraw( Image dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Rectangle dstRec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle srcRec = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t imageSrcId = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ size_t imageDstId = lua_tointeger( L, -1 );
+
+ if ( !validImage( imageDstId ) || !validImage( imageSrcId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDraw( state->images[ imageDstId ], *state->images[ imageSrcId ], srcRec, dstRec, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_ImageDrawTextEx( Image dst, Font font, string text, Vector2 position, float fontSize, float spacing, Color tint )
+
+Draw text ( Custom sprite font ) within an image ( Destination )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesImageDrawTextEx( lua_State *L ) {
+ if ( !lua_isnumber( L, -7 ) || !lua_isnumber( L, -6 ) || !lua_isstring( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_ImageDrawTextEx( Image dst, Font font, string text, Vector2 position, float fontSize, float spacing, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float spacing = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float fontSize = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 position = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t fontId = lua_tointeger( L, -2 );
+ size_t imageId = lua_tointeger( L, -3 );
+
+ if ( !validImage( imageId ) || !validFont( fontId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ ImageDrawTextEx( state->images[ imageId ], *state->fonts[ fontId ], lua_tostring( L, -1 ), position, fontSize, spacing, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+## Textures - Texture Drawing
+*/
+
+/*
+> success = RL_DrawTexture( Texture2D texture, Vector2 position, Color tint )
+
+Draw a Texture2D
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTexture( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTexture( Texture2D texture, Vector2 position, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 pos = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTexture( *texturesGetSourceTexture( texId ), pos.x, pos.y, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTextureRec( Texture2D texture, Rectangle source, Vector2 position, Color tint )
+
+Draw a part of a texture defined by a rectangle
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTextureRec( lua_State *L ) {
+ if ( !lua_isnumber( L, -4 ) || !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTextureRec( Texture2D texture, Rectangle source, Vector2 position, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ Vector2 pos = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle srcRect = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTextureRec( *texturesGetSourceTexture( texId ), srcRect, pos, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTextureTiled( Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint )
+
+Draw part of a texture ( defined by a rectangle ) with rotation and scale tiled into dest
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTextureTiled( lua_State *L ) {
+ if ( !lua_isnumber( L, -7 ) || !lua_istable( L, -6 ) || !lua_istable( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTextureTiled( Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float scale = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ float rot = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 origin = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle dstRect = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle srcRect = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTextureTiled( *texturesGetSourceTexture( texId ), srcRect, dstRect, origin, rot, scale, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTexturePro( Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint )
+
+Draw a part of a texture defined by a rectangle with "pro" parameters
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTexturePro( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_istable( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTexturePro( Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float rot = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 origin = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle dstRect = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ Rectangle srcRect = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTexturePro( *texturesGetSourceTexture( texId ), srcRect, dstRect, origin, rot, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTextureNPatch( Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint )
+
+Draws a texture ( or part of it ) that stretches or shrinks nicely
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTextureNPatch( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_istable( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTextureNPatch( Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color tint = uluaGetColor( L );
+ lua_pop( L, 1 );
+ float rotation = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 origin = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ Rectangle dest = uluaGetRectangle( L );
+ lua_pop( L, 1 );
+ NPatchInfo nPatchInfo = uluaGetNPatchInfo( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ DrawTextureNPatch( *texturesGetSourceTexture( texId ), nPatchInfo, dest, origin, rotation, tint );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_DrawTexturePoly( Texture2D texture, Vector2 center, Vector2{} points, Vector2{} texcoords, int pointsCount, Color tint )
+
+Draw a textured polygon ( Convex )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesDrawTexturePoly( lua_State *L ) {
+ if ( !lua_isnumber( L, -6 ) || !lua_istable( L, -5 ) || !lua_istable( L, -4 )
+ || !lua_istable( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_DrawTexturePoly( Texture2D texture, Vector2 center, Vector2 points{}, Vector2 texcoords{}, int pointsCount, Color tint )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Color color = uluaGetColor( L );
+ lua_pop( L, 1 );
+ int pointsCount = lua_tointeger( L, -1 );
+ lua_pop( L, 1 );
+ Vector2 texCoords[ pointsCount ];
+
+ int t = lua_gettop( L ), i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ texCoords[i] = uluaGetVector2( L );
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+
+ Vector2 points[ pointsCount ];
+
+ t = lua_gettop( L );
+ i = 0;
+ lua_pushnil( L );
+
+ while ( lua_next( L, t ) != 0 ) {
+ points[i] = uluaGetVector2( L );
+ i++;
+ lua_pop( L, 1 );
+ }
+ lua_pop( L, 1 );
+ Vector2 center = uluaGetVector2( L );
+ lua_pop( L, 1 );
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ DrawTexturePoly( *texturesGetSourceTexture( texId ), center, points, texCoords, pointsCount, color );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_BeginTextureMode( RenderTexture2D target )
+
+Begin drawing to render texture
+
+- Failure return false
+- Success return true
+*/
+int ltexturesBeginTextureMode( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_BeginTextureMode( RenderTexture2D target )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validRenderTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ BeginTextureMode( *state->renderTextures[ texId ] );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> RL_EndTextureMode()
+
+Ends drawing to render texture
+*/
+int ltexturesEndTextureMode( lua_State *L ) {
+ EndTextureMode();
+
+ return 1;
+}
+
+/*
+> success = RL_SetTextureSource( int textureSource )
+
+Set what texture source to use ( TEXTURE_SOURCE_TEXTURE or TEXTURE_SOURCE_RENDER_TEXTURE )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesSetTextureSource( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetTextureSource( int textureSource )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ int texSource = lua_tointeger( L, -1 );
+
+ if ( texSource != TEXTURE_SOURCE_TEXTURE && texSource != TEXTURE_SOURCE_RENDER_TEXTURE ) {
+ TraceLog( LOG_WARNING, "%s %d", "Invalid source texture", texSource );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ state->textureSource = texSource;
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> textureSource = RL_GetTextureSource()
+
+Get current texture source type ( TEXTURE_SOURCE_TEXTURE or TEXTURE_SOURCE_RENDER_TEXTURE )
+
+- Success return int
+*/
+int ltexturesGetTextureSource( lua_State *L ) {
+ lua_pushinteger( L, state->textureSource );
+
+ return 1;
+}
+
+/*
+## Textures - Configure
+*/
+
+/*
+> success = RL_GenTextureMipmaps( Texture2D texture )
+
+Generate GPU mipmaps for a texture
+
+- Failure return false
+- Success return true
+*/
+int ltexturesGenTextureMipmaps( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GenTextureMipmaps( Texture2D texture )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ GenTextureMipmaps( texturesGetSourceTexture( texId ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetTextureFilter( Texture2D texture, int filter )
+
+Set texture scaling filter mode ( TEXTURE_FILTER_POINT, TEXTURE_FILTER_BILINEAR... )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesSetTextureFilter( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetTextureFilter( Texture2D texture, int filter )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -2 );
+
+ if ( !validTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetTextureFilter( *texturesGetSourceTexture( texId ), lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> success = RL_SetTextureWrap( Texture2D texture, int wrap )
+
+Set texture wrapping mode ( TEXTURE_WRAP_REPEAT, TEXTURE_WRAP_CLAMP... )
+
+- Failure return false
+- Success return true
+*/
+int ltexturesSetTextureWrap( lua_State *L ) {
+ if ( !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_SetTextureWrap( Texture2D texture, int wrap )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -2 );
+
+ if ( !validTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ SetTextureWrap( *state->textures[ texId ], lua_tointeger( L, -1 ) );
+ lua_pushboolean( L, true );
+
+ return 1;
+}
+
+/*
+> size = RL_GetTextureSize( Texture2D texture )
+
+Get texture size
+
+- Failure return nil
+- Success return Vector2
+*/
+int ltexturesGetTextureSize( lua_State *L ) {
+ if ( !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_GetTextureSize( Texture2D texture )" );
+ lua_pushnil( L );
+ return 1;
+ }
+ size_t texId = lua_tointeger( L, -1 );
+
+ if ( !validSourceTexture( texId ) ) {
+ lua_pushboolean( L, false );
+ return 1;
+ }
+
+ Texture2D texture = *texturesGetSourceTexture( texId );
+ uluaPushVector2( L, (Vector2){ texture.width, texture.height } );
+
+ return 1;
+}