Browse Source

Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop

victorfisac 9 years ago
parent
commit
c453ac8265

+ 6 - 3
examples/core_3d_camera_first_person.c

@@ -74,10 +74,13 @@ int main()
                 }
                 }
 
 
             End3dMode();
             End3dMode();
+            
+            DrawRectangle( 10, 10, 220, 70, Fade(SKYBLUE, 0.5f));
+            DrawRectangleLines( 10, 10, 220, 70, BLUE);
 
 
-            DrawText("First person camera default controls:", 20, 20, 10, GRAY);
-            DrawText("- Move with keys: W, A, S, D", 40, 50, 10, DARKGRAY);
-            DrawText("- Mouse move to look around", 40, 70, 10, DARKGRAY);
+            DrawText("First person camera default controls:", 20, 20, 10, BLACK);
+            DrawText("- Move with keys: W, A, S, D", 40, 40, 10, DARKGRAY);
+            DrawText("- Mouse move to look around", 40, 60, 10, DARKGRAY);
 
 
         EndDrawing();
         EndDrawing();
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------

BIN
examples/core_3d_camera_first_person.png


+ 10 - 7
examples/core_3d_camera_free.c

@@ -59,13 +59,16 @@ int main()
                 DrawGrid(10, 1.0f);
                 DrawGrid(10, 1.0f);
 
 
             End3dMode();
             End3dMode();
-
-            DrawText("Free camera default controls:", 20, 20, 10, GRAY);
-            DrawText("- Mouse Wheel to Zoom in-out", 40, 50, 10, DARKGRAY);
-            DrawText("- Mouse Wheel Pressed to Pan", 40, 70, 10, DARKGRAY);
-            DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 90, 10, DARKGRAY);
-            DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 110, 10, DARKGRAY);
-            DrawText("- Z to zoom to (0, 0, 0)", 40, 130, 10, DARKGRAY);
+            
+            DrawRectangle( 10, 10, 320, 133, Fade(SKYBLUE, 0.5f));
+            DrawRectangleLines( 10, 10, 320, 133, BLUE);
+            
+            DrawText("Free camera default controls:", 20, 20, 10, BLACK);
+            DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY);
+            DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY);
+            DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, DARKGRAY);
+            DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, DARKGRAY);
+            DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, DARKGRAY);
 
 
         EndDrawing();
         EndDrawing();
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------

BIN
examples/core_3d_camera_free.png


+ 1 - 1
examples/core_3d_picking.c

@@ -77,7 +77,7 @@ int main()
 
 
             End3dMode();
             End3dMode();
             
             
-            DrawText("Try selecting the box with mouse!", 240, 10, 20, GRAY);
+            DrawText("Try selecting the box with mouse!", 240, 10, 20, DARKGRAY);
             
             
             if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN);
             if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN);
 
 

BIN
examples/shapes_basic_shapes.png


BIN
examples/textures_srcrec_dstrec.png


+ 91 - 84
src/core.c

@@ -116,9 +116,9 @@
 
 
 #if defined(PLATFORM_RPI)
 #if defined(PLATFORM_RPI)
     // Old device inputs system
     // Old device inputs system
-    #define DEFAULT_KEYBOARD_DEV      STDIN_FILENO            // Standard input
-    #define DEFAULT_MOUSE_DEV         "/dev/input/mouse0"
-    #define DEFAULT_GAMEPAD_DEV       "/dev/input/js0"
+    #define DEFAULT_KEYBOARD_DEV      STDIN_FILENO              // Standard input
+    #define DEFAULT_MOUSE_DEV         "/dev/input/mouse0"       // Mouse input
+    #define DEFAULT_GAMEPAD_DEV       "/dev/input/js"           // Gamepad input (base dev for all gamepads: js0, js1, ...)
 
 
     // New device input events (evdev) (must be detected)
     // New device input events (evdev) (must be detected)
     //#define DEFAULT_KEYBOARD_DEV    "/dev/input/eventN"
     //#define DEFAULT_KEYBOARD_DEV    "/dev/input/eventN"
@@ -126,7 +126,10 @@
     //#define DEFAULT_GAMEPAD_DEV     "/dev/input/eventN"
     //#define DEFAULT_GAMEPAD_DEV     "/dev/input/eventN"
     
     
     #define MOUSE_SENSITIVITY         0.8f
     #define MOUSE_SENSITIVITY         0.8f
-    #define MAX_GAMEPAD_BUTTONS       11
+    
+    #define MAX_GAMEPADS              2         // Max number of gamepads supported
+    #define MAX_GAMEPAD_BUTTONS       11        // Max bumber of buttons supported (per gamepad)
+    #define MAX_GAMEPAD_AXIS          8         // Max number of axis supported (per gamepad)
 #endif
 #endif
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -143,10 +146,12 @@ static bool windowMinimized = false;
 #elif defined(PLATFORM_ANDROID)
 #elif defined(PLATFORM_ANDROID)
 static struct android_app *app;                 // Android activity
 static struct android_app *app;                 // Android activity
 static struct android_poll_source *source;      // Android events polling source
 static struct android_poll_source *source;      // Android events polling source
-static int ident, events;
+static int ident, events;                       // Android ALooper_pollAll() variables
+
 static bool windowReady = false;                // Used to detect display initialization
 static bool windowReady = false;                // Used to detect display initialization
 static bool appEnabled = true;                  // Used to detec if app is active
 static bool appEnabled = true;                  // Used to detec if app is active
 static bool contextRebindRequired = false;      // Used to know context rebind required
 static bool contextRebindRequired = false;      // Used to know context rebind required
+
 static int previousButtonState[128] = { 1 };    // Required to check if button pressed/released once
 static int previousButtonState[128] = { 1 };    // Required to check if button pressed/released once
 static int currentButtonState[128] = { 1 };     // Required to check if button pressed/released once
 static int currentButtonState[128] = { 1 };     // Required to check if button pressed/released once
 #elif defined(PLATFORM_RPI)
 #elif defined(PLATFORM_RPI)
@@ -163,13 +168,12 @@ static bool mouseReady = false;                 // Flag to know if mouse is read
 pthread_t mouseThreadId;                        // Mouse reading thread id
 pthread_t mouseThreadId;                        // Mouse reading thread id
 
 
 // Gamepad input variables
 // Gamepad input variables
-static int gamepadStream = -1;                  // Gamepad device file descriptor
-static bool gamepadReady = false;               // Flag to know if gamepad is ready
-pthread_t gamepadThreadId;                      // Gamepad reading thread id
+static int gamepadStream[MAX_GAMEPADS] = { -1 };    // Gamepad device file descriptor (two gamepads supported)
+static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready (two gamepads supported)
+pthread_t gamepadThreadId;                          // Gamepad reading thread id
 
 
-int gamepadButtons[MAX_GAMEPAD_BUTTONS];
-int gamepadAxisX = 0;
-int gamepadAxisY = 0;
+int gamepadButtons[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS];        // Gamepad buttons state
+float gamepadAxisValues[MAX_GAMEPADS][MAX_GAMEPAD_AXIS];      // Gamepad axis state
 #endif
 #endif
 
 
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
@@ -191,9 +195,7 @@ static int renderOffsetY = 0;               // Offset Y from render area (must b
 static bool fullscreen = false;             // Fullscreen mode (useful only for PLATFORM_DESKTOP)
 static bool fullscreen = false;             // Fullscreen mode (useful only for PLATFORM_DESKTOP)
 static Matrix downscaleView;                // Matrix to downscale view (in case screen size bigger than display size)
 static Matrix downscaleView;                // Matrix to downscale view (in case screen size bigger than display size)
 
 
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
 static Vector2 touchPosition[MAX_TOUCH_POINTS];     // Touch position on screen
 static Vector2 touchPosition[MAX_TOUCH_POINTS];     // Touch position on screen
-#endif
 
 
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
 static const char *windowTitle;             // Window text title...
 static const char *windowTitle;             // Window text title...
@@ -401,13 +403,6 @@ void InitWindow(int width, int height, struct android_app *state)
 
 
     TraceLog(INFO, "Android app initialized successfully");
     TraceLog(INFO, "Android app initialized successfully");
 
 
-    // Init button states values (default up)
-    for(int i = 0; i < 128; i++)
-    {
-        currentButtonState[i] = 1;
-        previousButtonState[i] = 1;
-    }
-
     // Wait for window to be initialized (display and context)
     // Wait for window to be initialized (display and context)
     while (!windowReady)
     while (!windowReady)
     {
     {
@@ -641,6 +636,8 @@ void Begin3dMode(Camera camera)
     // Setup Camera view
     // Setup Camera view
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
     rlMultMatrixf(MatrixToFloat(matView));      // Multiply MODELVIEW matrix by view matrix (camera)
     rlMultMatrixf(MatrixToFloat(matView));      // Multiply MODELVIEW matrix by view matrix (camera)
+    
+    rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
 }
 }
 
 
 // Ends 3D mode and returns to default 2D orthographic mode
 // Ends 3D mode and returns to default 2D orthographic mode
@@ -655,6 +652,8 @@ void End3dMode(void)
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
 
 
     //rlTranslatef(0.375, 0.375, 0);      // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
     //rlTranslatef(0.375, 0.375, 0);      // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
+    
+    rlDisableDepthTest();               // Disable DEPTH_TEST for 2D
 }
 }
 
 
 // Set target FPS for the game
 // Set target FPS for the game
@@ -1168,7 +1167,7 @@ bool IsGamepadAvailable(int gamepad)
     bool result = false;
     bool result = false;
     
     
 #if defined(PLATFORM_RPI)
 #if defined(PLATFORM_RPI)
-    if (gamepadReady && (gamepad == 0)) result = true;
+    if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true;
 #else
 #else
     if (glfwJoystickPresent(gamepad) == 1) result = true;
     if (glfwJoystickPresent(gamepad) == 1) result = true;
 #endif
 #endif
@@ -1177,30 +1176,25 @@ bool IsGamepadAvailable(int gamepad)
 }
 }
 
 
 // Return axis movement vector for a gamepad
 // Return axis movement vector for a gamepad
-Vector2 GetGamepadMovement(int gamepad)
+float GetGamepadAxisMovement(int gamepad, int axis)
 {
 {
-    Vector2 vec = { 0, 0 };
-
-    const float *axes;
-    int axisCount = 0;
+    float value = 0;
     
     
 #if defined(PLATFORM_RPI)
 #if defined(PLATFORM_RPI)
-    // TODO: Get gamepad axis information
-    // Use gamepadAxisX, gamepadAxisY
+    if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad])
+    {
+        if (axis < MAX_GAMEPAD_AXIS) value = gamepadAxisValues[gamepad][axis];
+    }
 #else
 #else
+    const float *axes;
+    int axisCount = 0;
+    
     axes = glfwGetJoystickAxes(gamepad, &axisCount);
     axes = glfwGetJoystickAxes(gamepad, &axisCount);
-#endif
     
     
-    if (axisCount >= 2)
-    {
-        vec.x = axes[0];    // Left joystick X
-        vec.y = axes[1];    // Left joystick Y
-
-        //vec.x = axes[2];    // Right joystick X
-        //vec.x = axes[3];    // Right joystick Y
-    }
+    if (axis < axisCount) value = axes[axis];
+#endif
 
 
-    return vec;
+    return value;
 }
 }
 
 
 // Detect if a gamepad button has been pressed once
 // Detect if a gamepad button has been pressed once
@@ -1227,7 +1221,7 @@ bool IsGamepadButtonDown(int gamepad, int button)
     
     
 #if defined(PLATFORM_RPI)
 #if defined(PLATFORM_RPI)
     // Get gamepad buttons information
     // Get gamepad buttons information
-    if ((gamepad == 0) && (gamepadButtons[button] == 1)) result = true;
+    if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 1)) result = true;
     else result = false;
     else result = false;
 #else
 #else
     const unsigned char *buttons;
     const unsigned char *buttons;
@@ -1266,7 +1260,7 @@ bool IsGamepadButtonUp(int gamepad, int button)
 
 
 #if defined(PLATFORM_RPI)
 #if defined(PLATFORM_RPI)
     // Get gamepad buttons information
     // Get gamepad buttons information
-    if ((gamepad == 0) && (gamepadButtons[button] == 0)) result = true;
+    if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 0)) result = true;
     else result = false;
     else result = false;
 #else
 #else
     const unsigned char *buttons;
     const unsigned char *buttons;
@@ -1487,11 +1481,11 @@ static void InitDisplay(int width, int height)
         TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
         TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
     }
     }
 
 
-    glfwSetWindowSizeCallback(window, WindowSizeCallback);
+    glfwSetWindowSizeCallback(window, WindowSizeCallback);      // NOTE: Resizing not allowed by default!
     glfwSetCursorEnterCallback(window, CursorEnterCallback);
     glfwSetCursorEnterCallback(window, CursorEnterCallback);
     glfwSetKeyCallback(window, KeyCallback);
     glfwSetKeyCallback(window, KeyCallback);
     glfwSetMouseButtonCallback(window, MouseButtonCallback);
     glfwSetMouseButtonCallback(window, MouseButtonCallback);
-    glfwSetCursorPosCallback(window, MouseCursorPosCallback);    // Track mouse position changes
+    glfwSetCursorPosCallback(window, MouseCursorPosCallback);   // Track mouse position changes
     glfwSetCharCallback(window, CharCallback);
     glfwSetCharCallback(window, CharCallback);
     glfwSetScrollCallback(window, ScrollCallback);
     glfwSetScrollCallback(window, ScrollCallback);
     glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
     glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
@@ -1785,6 +1779,9 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
     GestureEvent gestureEvent;
     GestureEvent gestureEvent;
 
 
     gestureEvent.touchAction = TOUCH_MOVE;
     gestureEvent.touchAction = TOUCH_MOVE;
+    
+    // Assign a pointer ID
+    gestureEvent.pointerId[0] = 0;
 
 
     // Register touch points count
     // Register touch points count
     gestureEvent.pointCount = 1;
     gestureEvent.pointCount = 1;
@@ -1792,6 +1789,8 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
     // Register touch points position, only one point registered
     // Register touch points position, only one point registered
     gestureEvent.position[0] = (Vector2){ (float)x, (float)y };
     gestureEvent.position[0] = (Vector2){ (float)x, (float)y };
     
     
+    touchPosition[0] = gestureEvent.position[0];
+    
     // Normalize gestureEvent.position[0] for screenWidth and screenHeight
     // Normalize gestureEvent.position[0] for screenWidth and screenHeight
     gestureEvent.position[0].x /= (float)GetScreenWidth(); 
     gestureEvent.position[0].x /= (float)GetScreenWidth(); 
     gestureEvent.position[0].y /= (float)GetScreenHeight();
     gestureEvent.position[0].y /= (float)GetScreenHeight();
@@ -1817,16 +1816,19 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
 }
 }
 
 
 // GLFW3 WindowSize Callback, runs when window is resized
 // GLFW3 WindowSize Callback, runs when window is resized
+// NOTE: Window resizing not allowed by default
 static void WindowSizeCallback(GLFWwindow *window, int width, int height)
 static void WindowSizeCallback(GLFWwindow *window, int width, int height)
 {
 {
     // If window is resized, graphics device is re-initialized (but only ortho mode)
     // If window is resized, graphics device is re-initialized (but only ortho mode)
-    rlglInitGraphics(renderOffsetX, renderOffsetY, renderWidth, renderHeight);
+    rlglInitGraphics(0, 0, width, height);
 
 
     // Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
     // Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
-    //screenWidth = width;
-    //screenHeight = height;
-
-    // TODO: Update render size?
+    screenWidth = width;
+    screenHeight = height;
+    renderWidth = width;
+    renderHeight = height;
+    
+    // NOTE: Postprocessing texture is not scaled to new size
 
 
     // Background must be also re-cleared
     // Background must be also re-cleared
     ClearBackground(RAYWHITE);
     ClearBackground(RAYWHITE);
@@ -2455,19 +2457,31 @@ static void *MouseThread(void *arg)
 // Init gamepad system
 // Init gamepad system
 static void InitGamepad(void)
 static void InitGamepad(void)
 {
 {
-    if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) 
-    {
-        TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available");
-    }
-    else
+    char gamepadDev[128] = "";
+            
+    for (int i = 0; i < MAX_GAMEPADS; i++)
     {
     {
-        gamepadReady = true;
+        sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
+        
+        if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) 
+        {
+            // NOTE: Only show message for first gamepad
+            if (i == 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available");
+        }
+        else
+        {
+            gamepadReady[i] = true;
 
 
-        int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL);
+            // NOTE: Only create one thread
+            if (i == 0)
+            {
+                int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL);
 
 
-        if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread");
-        else  TraceLog(INFO, "Gamepad device initialized successfully");
-    }
+                if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread");
+                else  TraceLog(INFO, "Gamepad device initialized successfully");
+            }
+        }
+    }       
 }
 }
 
 
 // Process Gamepad (/dev/input/js0)
 // Process Gamepad (/dev/input/js0)
@@ -2484,45 +2498,38 @@ static void *GamepadThread(void *arg)
         unsigned char number;   // event axis/button number
         unsigned char number;   // event axis/button number
     };
     };
 
 
-    // These values are sensible on Logitech Dual Action Rumble and Xbox360 controller
-    const int joystickAxisX = 0;
-    const int joystickAxisY = 1;
-
     // Read gamepad event
     // Read gamepad event
 	struct js_event gamepadEvent;
 	struct js_event gamepadEvent;
     
     
 	while (1) 
 	while (1) 
     {
     {
-        if (read(gamepadStream, &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
+        for (int i = 0; i < MAX_GAMEPADS; i++)
         {
         {
-            gamepadEvent.type &= ~JS_EVENT_INIT;     // Ignore synthetic events
-            
-            // Process gamepad events by type
-            if (gamepadEvent.type == JS_EVENT_BUTTON) 
+            if (read(gamepadStream[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
             {
             {
-                TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value);
+                gamepadEvent.type &= ~JS_EVENT_INIT;     // Ignore synthetic events
                 
                 
-                if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) 
+                // Process gamepad events by type
+                if (gamepadEvent.type == JS_EVENT_BUTTON) 
                 {
                 {
-                    // 1 - button pressed, 0 - button released
-                    gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value;
+                    TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value);
+                    
+                    if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) 
+                    {
+                        // 1 - button pressed, 0 - button released
+                        gamepadButtons[i][gamepadEvent.number] = (int)gamepadEvent.value;
+                    }
                 }
                 }
-            }
-            else if (gamepadEvent.type == JS_EVENT_AXIS) 
-            {
-                TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value);
-                
-                if (gamepadEvent.number == joystickAxisX) gamepadAxisX = (int)gamepadEvent.value;
-                if (gamepadEvent.number == joystickAxisY) gamepadAxisY = (int)gamepadEvent.value;
-                /*
-                switch (gamepadEvent.number)
+                else if (gamepadEvent.type == JS_EVENT_AXIS) 
                 {
                 {
-                    case 0: // 1st Axis X
-                    case 1: // 1st Axis Y
-                    case 2: // 2st Axis X
-                    case 3: // 2st Axis Y
+                    TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value);
+                    
+                    if (gamepadEvent.number < MAX_GAMEPAD_AXIS)
+                    {
+                        // NOTE: Scaling of gamepadEvent.value to get values between -1..1
+                        gamepadAxisValues[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
+                    }
                 }
                 }
-                */
             }
             }
         }
         }
 	}
 	}

+ 2 - 0
src/gestures.c

@@ -179,6 +179,7 @@ void ProcessGestureEvent(GestureEvent event)
             }
             }
             
             
             touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
             touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
+            pointCount = 0;
         }
         }
         else if (event.touchAction == TOUCH_MOVE)
         else if (event.touchAction == TOUCH_MOVE)
         {
         {
@@ -257,6 +258,7 @@ void ProcessGestureEvent(GestureEvent event)
             pinchDistance = 0.0f;
             pinchDistance = 0.0f;
             pinchAngle = 0.0f;
             pinchAngle = 0.0f;
             pinchVector = (Vector2){ 0.0f, 0.0f };
             pinchVector = (Vector2){ 0.0f, 0.0f };
+            pointCount = 0;
             
             
             currentGesture = GESTURE_NONE;
             currentGesture = GESTURE_NONE;
         }
         }

+ 32 - 4
src/raylib.h

@@ -174,8 +174,8 @@
 // Gamepad Number
 // Gamepad Number
 #define GAMEPAD_PLAYER1       0
 #define GAMEPAD_PLAYER1       0
 #define GAMEPAD_PLAYER2       1
 #define GAMEPAD_PLAYER2       1
-#define GAMEPAD_PLAYER3       2
-#define GAMEPAD_PLAYER4       3
+#define GAMEPAD_PLAYER3       2     // Not supported
+#define GAMEPAD_PLAYER4       3     // Not supported
 
 
 // Gamepad Buttons
 // Gamepad Buttons
 // NOTE: Adjusted for a PS3 USB Controller
 // NOTE: Adjusted for a PS3 USB Controller
@@ -190,7 +190,35 @@
 #define GAMEPAD_BUTTON_SELECT   9
 #define GAMEPAD_BUTTON_SELECT   9
 #define GAMEPAD_BUTTON_START   10
 #define GAMEPAD_BUTTON_START   10
 
 
-// TODO: Review Xbox360 USB Controller Buttons
+// Xbox360 USB Controller Buttons
+#define GAMEPAD_XBOX_BUTTON_A       0
+#define GAMEPAD_XBOX_BUTTON_B       1
+#define GAMEPAD_XBOX_BUTTON_X       2
+#define GAMEPAD_XBOX_BUTTON_Y       3
+#define GAMEPAD_XBOX_BUTTON_LB      4
+#define GAMEPAD_XBOX_BUTTON_RB      5
+#define GAMEPAD_XBOX_BUTTON_SELECT  6
+#define GAMEPAD_XBOX_BUTTON_START   7
+
+#if defined(PLATFORM_RPI)
+    #define GAMEPAD_XBOX_AXIS_DPAD_X    7
+    #define GAMEPAD_XBOX_AXIS_DPAD_Y    6
+    #define GAMEPAD_XBOX_AXIS_RIGHT_X   3
+    #define GAMEPAD_XBOX_AXIS_RIGHT_Y   4
+    #define GAMEPAD_XBOX_AXIS_LT        2
+    #define GAMEPAD_XBOX_AXIS_RT        5
+#else
+    #define GAMEPAD_XBOX_BUTTON_UP      10
+    #define GAMEPAD_XBOX_BUTTON_DOWN    12
+    #define GAMEPAD_XBOX_BUTTON_LEFT    13
+    #define GAMEPAD_XBOX_BUTTON_RIGHT   11
+    #define GAMEPAD_XBOX_AXIS_RIGHT_X   4
+    #define GAMEPAD_XBOX_AXIS_RIGHT_Y   3
+    #define GAMEPAD_XBOX_AXIS_LT_RT     2
+#endif
+
+#define GAMEPAD_XBOX_AXIS_LEFT_X    0
+#define GAMEPAD_XBOX_AXIS_LEFT_Y    1
 
 
 // Android Physic Buttons
 // Android Physic Buttons
 #define ANDROID_BACK            4
 #define ANDROID_BACK            4
@@ -592,7 +620,7 @@ void DisableCursor(void);                               // Disables cursor
 bool IsCursorHidden(void);                              // Returns true if cursor is not visible
 bool IsCursorHidden(void);                              // Returns true if cursor is not visible
 
 
 bool IsGamepadAvailable(int gamepad);                   // Detect if a gamepad is available
 bool IsGamepadAvailable(int gamepad);                   // Detect if a gamepad is available
-Vector2 GetGamepadMovement(int gamepad);                // Return axis movement vector for a gamepad
+float GetGamepadAxisMovement(int gamepad, int axis);    // Return axis movement value for a gamepad axis
 bool IsGamepadButtonPressed(int gamepad, int button);   // Detect if a gamepad button has been pressed once
 bool IsGamepadButtonPressed(int gamepad, int button);   // Detect if a gamepad button has been pressed once
 bool IsGamepadButtonDown(int gamepad, int button);      // Detect if a gamepad button is being pressed
 bool IsGamepadButtonDown(int gamepad, int button);      // Detect if a gamepad button is being pressed
 bool IsGamepadButtonReleased(int gamepad, int button);  // Detect if a gamepad button has been released once
 bool IsGamepadButtonReleased(int gamepad, int button);  // Detect if a gamepad button has been released once

+ 69 - 11
src/rlgl.c

@@ -32,7 +32,9 @@
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand()
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand()
 #include <string.h>         // Declares strcmp(), strlen(), strtok()
 #include <string.h>         // Declares strcmp(), strlen(), strtok()
 
 
-#include "raymath.h"        // Required for Vector3 and Matrix functions
+#ifndef RLGL_STANDALONE
+    #include "raymath.h"    // Required for Vector3 and Matrix functions
+#endif
 
 
 #if defined(GRAPHICS_API_OPENGL_11)
 #if defined(GRAPHICS_API_OPENGL_11)
     #ifdef __APPLE__                // OpenGL include for OSX
     #ifdef __APPLE__                // OpenGL include for OSX
@@ -186,6 +188,8 @@ typedef struct {
 // Framebuffer Object type
 // Framebuffer Object type
 typedef struct {
 typedef struct {
     GLuint id;
     GLuint id;
+    int width;
+    int height;
     GLuint colorTextureId;
     GLuint colorTextureId;
     GLuint depthTextureId;
     GLuint depthTextureId;
 } FBO;
 } FBO;
@@ -298,6 +302,7 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
 
 
 #if defined(RLGL_STANDALONE)
 #if defined(RLGL_STANDALONE)
 static void TraceLog(int msgType, const char *text, ...);
 static void TraceLog(int msgType, const char *text, ...);
+float *MatrixToFloat(Matrix mat);   // Converts Matrix to float array
 #endif
 #endif
 
 
 #if defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_ES2)
@@ -780,6 +785,18 @@ void rlDisableTexture(void)
 #endif
 #endif
 }
 }
 
 
+// Enable depth test
+void rlEnableDepthTest(void)
+{
+    glEnable(GL_DEPTH_TEST);
+}
+
+// Disable depth test
+void rlDisableDepthTest(void)
+{
+    glDisable(GL_DEPTH_TEST);
+}
+
 // Unload texture from GPU memory
 // Unload texture from GPU memory
 void rlDeleteTextures(unsigned int id)
 void rlDeleteTextures(unsigned int id)
 {
 {
@@ -1056,8 +1073,8 @@ void rlglInitPostpro(void)
         
         
         quad.vertexCount = 6;
         quad.vertexCount = 6;
         
         
-        float w = (float)screenWidth;
-        float h = (float)screenHeight;
+        float w = (float)postproFbo.width;
+        float h = (float)postproFbo.height;
         
         
         float quadPositions[6*3] = { w, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, h, 0.0f, 0.0f, h, 0.0f, w, h, 0.0f, w, 0.0f, 0.0f }; 
         float quadPositions[6*3] = { w, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, h, 0.0f, 0.0f, h, 0.0f, w, h, 0.0f, w, 0.0f, 0.0f }; 
         float quadTexcoords[6*2] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
         float quadTexcoords[6*2] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
@@ -1081,6 +1098,8 @@ FBO rlglLoadFBO(int width, int height)
 {
 {
     FBO fbo;   
     FBO fbo;   
     fbo.id = 0;
     fbo.id = 0;
+    fbo.width = width;
+    fbo.height = height;
 
 
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     // Create the texture that will serve as the color attachment for the framebuffer
     // Create the texture that will serve as the color attachment for the framebuffer
@@ -1579,7 +1598,7 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
     //glClearDepth(1.0f);                                   // Clear depth buffer (default)
     //glClearDepth(1.0f);                                   // Clear depth buffer (default)
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear used buffers, depth buffer is used for 3D
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear used buffers, depth buffer is used for 3D
 
 
-    glEnable(GL_DEPTH_TEST);                                // Enables depth testing (required for 3D)
+    glDisable(GL_DEPTH_TEST);                               // Disable depth testing for 2D (only used for 3D)
     glDepthFunc(GL_LEQUAL);                                 // Type of depth testing to apply
     glDepthFunc(GL_LEQUAL);                                 // Type of depth testing to apply
 
 
     glEnable(GL_BLEND);                                     // Enable color blending (required to work with transparencies)
     glEnable(GL_BLEND);                                     // Enable color blending (required to work with transparencies)
@@ -2324,22 +2343,21 @@ void SetCustomShader(Shader shader)
 }
 }
 
 
 // Set postprocessing shader
 // Set postprocessing shader
-// NOTE: Uses global variables screenWidth and screenHeight
 void SetPostproShader(Shader shader)
 void SetPostproShader(Shader shader)
 {
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     if (!enabledPostpro)
     if (!enabledPostpro)
     {
     {
         enabledPostpro = true;
         enabledPostpro = true;
-        rlglInitPostpro();
+        rlglInitPostpro();      // Lazy initialization on postprocessing usage
     }
     }
 
 
     SetModelShader(&postproQuad, shader);
     SetModelShader(&postproQuad, shader);
     
     
     Texture2D texture;
     Texture2D texture;
     texture.id = postproFbo.colorTextureId;
     texture.id = postproFbo.colorTextureId;
-    texture.width = screenWidth;
-    texture.height = screenHeight;
+    texture.width = postproFbo.width;
+    texture.height = postproFbo.height;
 
 
     postproQuad.material.texDiffuse = texture;
     postproQuad.material.texDiffuse = texture;
     
     
@@ -2569,6 +2587,7 @@ static Shader LoadDefaultShader(void)
     char fShaderStr[] = "#version 330       \n"
     char fShaderStr[] = "#version 330       \n"
         "in vec2 fragTexCoord;              \n"
         "in vec2 fragTexCoord;              \n"
         "in vec4 fragTintColor;             \n"
         "in vec4 fragTintColor;             \n"
+        "out vec4 fragColor;                \n"
 #elif defined(GRAPHICS_API_OPENGL_ES2)
 #elif defined(GRAPHICS_API_OPENGL_ES2)
     char fShaderStr[] = "#version 100       \n"
     char fShaderStr[] = "#version 100       \n"
         "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
         "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
@@ -2578,8 +2597,13 @@ static Shader LoadDefaultShader(void)
         "uniform sampler2D texture0;        \n"
         "uniform sampler2D texture0;        \n"
         "void main()                        \n"
         "void main()                        \n"
         "{                                  \n"
         "{                                  \n"
-        "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n"   // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0, use texture() instead
-        "    gl_FragColor = texelColor*fragTintColor; \n"    
+#if defined(GRAPHICS_API_OPENGL_33)
+        "    vec4 texelColor = texture(texture0, fragTexCoord); \n"
+        "    fragColor = texelColor*fragTintColor; \n"
+#elif defined(GRAPHICS_API_OPENGL_ES2)
+        "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
+        "    gl_FragColor = texelColor*fragTintColor; \n"
+#endif
         "}                                  \n";
         "}                                  \n";
 
 
     shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
     shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
@@ -2639,6 +2663,7 @@ static Shader LoadSimpleShader(void)
 #if defined(GRAPHICS_API_OPENGL_33)
 #if defined(GRAPHICS_API_OPENGL_33)
     char fShaderStr[] = "#version 330       \n"
     char fShaderStr[] = "#version 330       \n"
         "in vec2 fragTexCoord;              \n"
         "in vec2 fragTexCoord;              \n"
+        "out vec4 fragColor;                \n"
 #elif defined(GRAPHICS_API_OPENGL_ES2)
 #elif defined(GRAPHICS_API_OPENGL_ES2)
     char fShaderStr[] = "#version 100       \n"
     char fShaderStr[] = "#version 100       \n"
         "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
         "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
@@ -2648,8 +2673,13 @@ static Shader LoadSimpleShader(void)
         "uniform vec4 fragTintColor;        \n"
         "uniform vec4 fragTintColor;        \n"
         "void main()                        \n"
         "void main()                        \n"
         "{                                  \n"
         "{                                  \n"
-        "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n"   // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0, use texture() instead
+#if defined(GRAPHICS_API_OPENGL_33)
+        "    vec4 texelColor = texture(texture0, fragTexCoord); \n"
+        "    fragColor = texelColor*fragTintColor; \n"
+#elif defined(GRAPHICS_API_OPENGL_ES2)
+        "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
         "    gl_FragColor = texelColor*fragTintColor; \n"
         "    gl_FragColor = texelColor*fragTintColor; \n"
+#endif
         "}                                  \n";
         "}                                  \n";
 
 
     shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
     shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
@@ -3090,4 +3120,32 @@ static void TraceLog(int msgType, const char *text, ...)
 
 
     if (msgType == ERROR) exit(1);
     if (msgType == ERROR) exit(1);
 }
 }
+
+// Converts Matrix to float array
+// NOTE: Returned vector is a transposed version of the Matrix struct, 
+// it should be this way because, despite raymath use OpenGL column-major convention,
+// Matrix struct memory alignment and variables naming are not coherent
+float *MatrixToFloat(Matrix mat)
+{
+    static float buffer[16];
+
+    buffer[0] = mat.m0;
+    buffer[1] = mat.m4;
+    buffer[2] = mat.m8;
+    buffer[3] = mat.m12;
+    buffer[4] = mat.m1;
+    buffer[5] = mat.m5;
+    buffer[6] = mat.m9;
+    buffer[7] = mat.m13;
+    buffer[8] = mat.m2;
+    buffer[9] = mat.m6;
+    buffer[10] = mat.m10;
+    buffer[11] = mat.m14;
+    buffer[12] = mat.m3;
+    buffer[13] = mat.m7;
+    buffer[14] = mat.m11;
+    buffer[15] = mat.m15;
+
+    return buffer;
+}
 #endif
 #endif

+ 7 - 1
src/rlgl.h

@@ -36,7 +36,11 @@
     #include "utils.h"          // Required for function TraceLog()
     #include "utils.h"          // Required for function TraceLog()
 #endif
 #endif
 
 
-#include "raymath.h"
+#ifdef RLGL_STANDALONE
+    #define RAYMATH_STANDALONE
+#endif
+
+#include "raymath.h"            // Required for types: Vector3, Matrix
 
 
 // Select desired OpenGL version
 // Select desired OpenGL version
 // NOTE: Those preprocessor defines are only used on rlgl module,
 // NOTE: Those preprocessor defines are only used on rlgl module,
@@ -244,6 +248,8 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 void rlEnableTexture(unsigned int id);          // Enable texture usage
 void rlEnableTexture(unsigned int id);          // Enable texture usage
 void rlDisableTexture(void);                    // Disable texture usage
 void rlDisableTexture(void);                    // Disable texture usage
+void rlEnableDepthTest(void);                   // Enable depth test
+void rlDisableDepthTest(void);                  // Disable depth test
 void rlDeleteTextures(unsigned int id);         // Delete OpenGL texture from GPU
 void rlDeleteTextures(unsigned int id);         // Delete OpenGL texture from GPU
 void rlDeleteShader(unsigned int id);           // Delete OpenGL shader program from GPU
 void rlDeleteShader(unsigned int id);           // Delete OpenGL shader program from GPU
 void rlDeleteVertexArrays(unsigned int id);     // Unload vertex data (VAO) from GPU memory
 void rlDeleteVertexArrays(unsigned int id);     // Unload vertex data (VAO) from GPU memory

+ 110 - 34
src/shapes.c

@@ -98,7 +98,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
 // Draw a color-filled circle
 // Draw a color-filled circle
 void DrawCircle(int centerX, int centerY, float radius, Color color)
 void DrawCircle(int centerX, int centerY, float radius, Color color)
 {
 {
-    DrawPoly((Vector2){ centerX, centerY }, 36, radius, 0, color);
+    DrawCircleV((Vector2){ centerX, centerY }, radius, color);
 }
 }
 
 
 // Draw a gradient-filled circle
 // Draw a gradient-filled circle
@@ -119,17 +119,40 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
 }
 }
 
 
 // Draw a color-filled circle (Vector version)
 // Draw a color-filled circle (Vector version)
+// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
 void DrawCircleV(Vector2 center, float radius, Color color)
 void DrawCircleV(Vector2 center, float radius, Color color)
 {
 {
-    rlBegin(RL_TRIANGLES);
-        for (int i = 0; i < 360; i += 10)
-        {
-            rlColor4ub(color.r, color.g, color.b, color.a);
-            rlVertex2i(center.x, center.y);
-            rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
-            rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius);
-        }
-    rlEnd();
+    if (rlGetVersion() == OPENGL_11)
+    {
+        rlBegin(RL_TRIANGLES);
+            for (int i = 0; i < 360; i += 10)
+            {
+                rlColor4ub(color.r, color.g, color.b, color.a);
+                
+                rlVertex2i(center.x, center.y);
+                rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
+                rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius);
+            }
+        rlEnd();
+    }
+    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    {
+        rlEnableTexture(whiteTexture); // Default white texture
+
+        rlBegin(RL_QUADS);
+            for (int i = 0; i < 360; i += 20)
+            {
+                rlColor4ub(color.r, color.g, color.b, color.a);
+                
+                rlVertex2i(center.x, center.y);
+                rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
+                rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius);
+                rlVertex2f(center.x + sin(DEG2RAD*(i + 20)) * radius, center.y + cos(DEG2RAD*(i + 20)) * radius);
+            }
+        rlEnd();
+        
+        rlDisableTexture();
+    }
 }
 }
 
 
 // Draw circle outline
 // Draw circle outline
@@ -178,38 +201,76 @@ void DrawRectangleGradient(int posX, int posY, int width, int height, Color colo
 }
 }
 
 
 // Draw a color-filled rectangle (Vector version)
 // Draw a color-filled rectangle (Vector version)
+// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
 void DrawRectangleV(Vector2 position, Vector2 size, Color color)
 void DrawRectangleV(Vector2 position, Vector2 size, Color color)
 {
 {
-    rlBegin(RL_TRIANGLES);
-        rlColor4ub(color.r, color.g, color.b, color.a);
+    if (rlGetVersion() == OPENGL_11)
+    {
+        rlBegin(RL_TRIANGLES);
+            rlColor4ub(color.r, color.g, color.b, color.a);
 
 
-        rlVertex2i(position.x, position.y);
-        rlVertex2i(position.x, position.y + size.y);
-        rlVertex2i(position.x + size.x, position.y + size.y);
+            rlVertex2i(position.x, position.y);
+            rlVertex2i(position.x, position.y + size.y);
+            rlVertex2i(position.x + size.x, position.y + size.y);
 
 
-        rlVertex2i(position.x, position.y);
-        rlVertex2i(position.x + size.x, position.y + size.y);
-        rlVertex2i(position.x + size.x, position.y);
-    rlEnd();
+            rlVertex2i(position.x, position.y);
+            rlVertex2i(position.x + size.x, position.y + size.y);
+            rlVertex2i(position.x + size.x, position.y);
+        rlEnd();
+    }
+    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    {
+        rlEnableTexture(whiteTexture); // Default white texture
+
+        rlBegin(RL_QUADS);
+            rlColor4ub(color.r, color.g, color.b, color.a);
+            rlNormal3f(0.0f, 0.0f, 1.0f);
+
+            rlTexCoord2f(0.0f, 0.0f);
+            rlVertex2f(position.x, position.y);
+
+            rlTexCoord2f(0.0f, 1.0f);
+            rlVertex2f(position.x, position.y + size.y);
+
+            rlTexCoord2f(1.0f, 1.0f);
+            rlVertex2f(position.x + size.x, position.y + size.y);
+
+            rlTexCoord2f(1.0f, 0.0f);
+            rlVertex2f(position.x + size.x, position.y);
+        rlEnd();
+
+        rlDisableTexture();
+    }
 }
 }
 
 
 // Draw rectangle outline
 // Draw rectangle outline
+// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
 void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
 void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
-{
-    rlBegin(RL_LINES);
-        rlColor4ub(color.r, color.g, color.b, color.a);
-        rlVertex2i(posX + 1, posY + 1);
-        rlVertex2i(posX + width, posY + 1);
+{   
+    if (rlGetVersion() == OPENGL_11)
+    {
+        rlBegin(RL_LINES);
+            rlColor4ub(color.r, color.g, color.b, color.a);
+            rlVertex2i(posX + 1, posY + 1);
+            rlVertex2i(posX + width, posY + 1);
 
 
-        rlVertex2i(posX + width, posY + 1);
-        rlVertex2i(posX + width, posY + height);
+            rlVertex2i(posX + width, posY + 1);
+            rlVertex2i(posX + width, posY + height);
 
 
-        rlVertex2i(posX + width, posY + height);
-        rlVertex2i(posX + 1, posY + height);
+            rlVertex2i(posX + width, posY + height);
+            rlVertex2i(posX + 1, posY + height);
 
 
-        rlVertex2i(posX + 1, posY + height);
-        rlVertex2i(posX + 1, posY + 1);
-    rlEnd();
+            rlVertex2i(posX + 1, posY + height);
+            rlVertex2i(posX + 1, posY + 1);
+        rlEnd();
+    }
+    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    {
+        DrawRectangle(posX, posY, width, 1, color);
+        DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
+        DrawRectangle(posX, posY + height - 1, width, 1, color);
+        DrawRectangle(posX, posY + 1, 1, height - 2, color);
+    }
 }
 }
 
 
 // Draw a triangle
 // Draw a triangle
@@ -429,9 +490,24 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
                 retRec.height = rec2.height - dyy;
                 retRec.height = rec2.height - dyy;
             }
             }
         }
         }
-
-        if (retRec.width >= rec2.width) retRec.width = rec2.width;
-        if (retRec.height >= rec2.height) retRec.height = rec2.height;
+		
+        if (rec1.width > rec2.width)
+        {
+            if (retRec.width >= rec2.width) retRec.width = rec2.width;
+        }
+        else
+        {
+            if (retRec.width >= rec1.width) retRec.width = rec1.width;
+        }
+        
+        if (rec1.height > rec2.height)
+        {
+            if (retRec.height >= rec2.height) retRec.height = rec2.height;
+        }
+        else
+        {
+           if (retRec.height >= rec1.height) retRec.height = rec1.height;
+        }
     }
     }
 
 
     return retRec;
     return retRec;