From 6e4fdd3b3ae4e4656e151f098c40cfe551a36e8c Mon Sep 17 00:00:00 2001 From: jussi Date: Fri, 18 Feb 2022 18:27:10 +0200 Subject: Added initial files. --- src/audio.c | 272 ++++++++ src/core.c | 1908 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lua_core.c | 1033 +++++++++++++++++++++++++++ src/main.c | 37 + src/models.c | 2113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rgui.c | 544 +++++++++++++++ src/rmath.c | 978 ++++++++++++++++++++++++++ src/shapes.c | 457 ++++++++++++ src/state.c | 194 ++++++ src/text.c | 102 +++ src/textures.c | 1057 ++++++++++++++++++++++++++++ 11 files changed, 8695 insertions(+) create mode 100644 src/audio.c create mode 100644 src/core.c create mode 100644 src/lua_core.c create mode 100644 src/main.c create mode 100644 src/models.c create mode 100644 src/rgui.c create mode 100644 src/rmath.c create mode 100644 src/shapes.c create mode 100644 src/state.c create mode 100644 src/text.c create mode 100644 src/textures.c (limited to 'src') 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; +} -- cgit v1.2.3