Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f79c0d66ca
6
.github/workflows/build_android.yml
vendored
6
.github/workflows/build_android.yml
vendored
|
|
@ -84,8 +84,10 @@ jobs:
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NAME }}.tar.gz
|
name: ${{ env.RELEASE_NAME }}
|
||||||
path: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
path: |
|
||||||
|
./build/${{ env.RELEASE_NAME }}
|
||||||
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|
|
||||||
6
.github/workflows/build_linux.yml
vendored
6
.github/workflows/build_linux.yml
vendored
|
|
@ -114,8 +114,10 @@ jobs:
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NAME }}.tar.gz
|
name: ${{ env.RELEASE_NAME }}
|
||||||
path: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
path: |
|
||||||
|
./build/${{ env.RELEASE_NAME }}
|
||||||
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|
|
||||||
6
.github/workflows/build_macos.yml
vendored
6
.github/workflows/build_macos.yml
vendored
|
|
@ -101,8 +101,10 @@ jobs:
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NAME }}.tar.gz
|
name: ${{ env.RELEASE_NAME }}
|
||||||
path: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
path: |
|
||||||
|
./build/${{ env.RELEASE_NAME }}
|
||||||
|
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|
|
||||||
6
.github/workflows/build_webassembly.yml
vendored
6
.github/workflows/build_webassembly.yml
vendored
|
|
@ -71,8 +71,10 @@ jobs:
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NAME }}.zip
|
name: ${{ env.RELEASE_NAME }}
|
||||||
path: ./build/${{ env.RELEASE_NAME }}.zip
|
path: |
|
||||||
|
./build/${{ env.RELEASE_NAME }}
|
||||||
|
!./build/${{ env.RELEASE_NAME }}.zip
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|
|
||||||
6
.github/workflows/build_windows.yml
vendored
6
.github/workflows/build_windows.yml
vendored
|
|
@ -142,8 +142,10 @@ jobs:
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NAME }}.zip
|
name: ${{ env.RELEASE_NAME }}
|
||||||
path: ./build/${{ env.RELEASE_NAME }}.zip
|
path: |
|
||||||
|
./build/${{ env.RELEASE_NAME }}
|
||||||
|
!./build/${{ env.RELEASE_NAME }}.zip
|
||||||
|
|
||||||
- name: Upload Artifact to Release
|
- name: Upload Artifact to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
|
|
|
||||||
|
|
@ -226,10 +226,10 @@ void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envI
|
||||||
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
|
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
|
||||||
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
|
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
|
||||||
|
|
||||||
if (max.x < width) camera->offset.x = width - (max.x - width/2);
|
if (max.x < width) camera->offset.x = width - (max.x - (float)width/2);
|
||||||
if (max.y < height) camera->offset.y = height - (max.y - height/2);
|
if (max.y < height) camera->offset.y = height - (max.y - (float)height/2);
|
||||||
if (min.x > 0) camera->offset.x = width/2 - min.x;
|
if (min.x > 0) camera->offset.x = (float)width/2 - min.x;
|
||||||
if (min.y > 0) camera->offset.y = height/2 - min.y;
|
if (min.y > 0) camera->offset.y = (float)height/2 - min.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||||
|
|
|
||||||
|
|
@ -225,10 +225,10 @@ int main(void)
|
||||||
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera);
|
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera);
|
||||||
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera);
|
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera);
|
||||||
|
|
||||||
if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - screenWidth/2);
|
if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - (float)screenWidth/2);
|
||||||
if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - screenHeight/2);
|
if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - (float)screenHeight/2);
|
||||||
if (min.x > 0) camera.offset.x = screenWidth/2 - min.x;
|
if (min.x > 0) camera.offset.x = (float)screenWidth/2 - min.x;
|
||||||
if (min.y > 0) camera.offset.y = screenHeight/2 - min.y;
|
if (min.y > 0) camera.offset.y = (float)screenHeight/2 - min.y;
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Events management
|
// Events management
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gam
|
||||||
|
|
||||||
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
|
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
|
||||||
{
|
{
|
||||||
const float resizeRatio = (float)(screenHeight/gameHeight);
|
const float resizeRatio = (float)screenHeight/gameHeight;
|
||||||
sourceRect->x = 0.0f;
|
sourceRect->x = 0.0f;
|
||||||
sourceRect->y = 0.0f;
|
sourceRect->y = 0.0f;
|
||||||
sourceRect->width = (float)(int)(screenWidth/resizeRatio);
|
sourceRect->width = (float)(int)(screenWidth/resizeRatio);
|
||||||
|
|
@ -230,7 +230,7 @@ static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gam
|
||||||
|
|
||||||
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
|
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
|
||||||
{
|
{
|
||||||
const float resizeRatio = (float)(screenWidth/gameWidth);
|
const float resizeRatio = (float)screenWidth/gameWidth;
|
||||||
sourceRect->x = 0.0f;
|
sourceRect->x = 0.0f;
|
||||||
sourceRect->y = 0.0f;
|
sourceRect->y = 0.0f;
|
||||||
sourceRect->width = (float)gameWidth;
|
sourceRect->width = (float)gameWidth;
|
||||||
|
|
|
||||||
|
|
@ -148,25 +148,25 @@ void DrawSphereBasic(Color color)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < slices; j++)
|
for (int j = 0; j < slices; j++)
|
||||||
{
|
{
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360.0f/slices)));
|
||||||
|
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i))),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i))),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
|
||||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
|
||||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
|
||||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,9 @@ int main(void)
|
||||||
|
|
||||||
// Calculate the cube position
|
// Calculate the cube position
|
||||||
Vector3 cubePos = {
|
Vector3 cubePos = {
|
||||||
(float)(x - numBlocks/2)*(scale*3.0f) + scatter,
|
(float)(x - (float)numBlocks/2)*(scale*3.0f) + scatter,
|
||||||
(float)(y - numBlocks/2)*(scale*2.0f) + scatter,
|
(float)(y - (float)numBlocks/2)*(scale*2.0f) + scatter,
|
||||||
(float)(z - numBlocks/2)*(scale*3.0f) + scatter
|
(float)(z - (float)numBlocks/2)*(scale*3.0f) + scatter
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick a color with a hue depending on cube position for the rainbow color effect
|
// Pick a color with a hue depending on cube position for the rainbow color effect
|
||||||
|
|
|
||||||
|
|
@ -258,8 +258,8 @@ int main(void)
|
||||||
UnloadImage(pattern);
|
UnloadImage(pattern);
|
||||||
|
|
||||||
mode = MODE_PAUSE;
|
mode = MODE_PAUSE;
|
||||||
offsetX = worldWidth*presetPatterns[preset].position.x - windowWidth/zoom/2.0f;
|
offsetX = worldWidth*presetPatterns[preset].position.x - (float)windowWidth/zoom/2.0f;
|
||||||
offsetY = worldHeight*presetPatterns[preset].position.y - windowHeight/zoom/2.0f;
|
offsetY = worldHeight*presetPatterns[preset].position.y - (float)windowHeight/zoom/2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check window draw inside world limits
|
// Check window draw inside world limits
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ int main(void)
|
||||||
for (int i = 0; i < MAX_COLORS_COUNT; i++)
|
for (int i = 0; i < MAX_COLORS_COUNT; i++)
|
||||||
{
|
{
|
||||||
colorsRecs[i].x = 20.0f + 100.0f *(i%7) + 10.0f *(i%7);
|
colorsRecs[i].x = 20.0f + 100.0f *(i%7) + 10.0f *(i%7);
|
||||||
colorsRecs[i].y = 80.0f + 100.0f *(i/7) + 10.0f *(i/7);
|
colorsRecs[i].y = 80.0f + 100.0f *((float)i/7) + 10.0f *((float)i/7);
|
||||||
colorsRecs[i].width = 100.0f;
|
colorsRecs[i].width = 100.0f;
|
||||||
colorsRecs[i].height = 100.0f;
|
colorsRecs[i].height = 100.0f;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ static void DrawDisplaySegment(Vector2 center, int length, int thick, bool verti
|
||||||
(Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3
|
(Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3
|
||||||
(Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4
|
(Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4
|
||||||
(Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5
|
(Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5
|
||||||
(Vector2){ center.x, center.y + length/2 + thick/2.0f }, // Point 6
|
(Vector2){ center.x, center.y + (float)length/2 + thick/2.0f }, // Point 6
|
||||||
};
|
};
|
||||||
|
|
||||||
DrawTriangleStrip(segmentPointsV, 6, color);
|
DrawTriangleStrip(segmentPointsV, 6, color);
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ int main(void)
|
||||||
float totalM = m1 + m2;
|
float totalM = m1 + m2;
|
||||||
|
|
||||||
Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
||||||
previousPosition.x += (screenWidth/2);
|
previousPosition.x += ((float)screenWidth/2);
|
||||||
previousPosition.y += (screenHeight/2 - 100);
|
previousPosition.y += ((float)screenHeight/2 - 100);
|
||||||
|
|
||||||
// Scale length
|
// Scale length
|
||||||
float L1 = l1*lengthScaler;
|
float L1 = l1*lengthScaler;
|
||||||
|
|
@ -105,8 +105,8 @@ int main(void)
|
||||||
|
|
||||||
// Calculate position
|
// Calculate position
|
||||||
Vector2 currentPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
Vector2 currentPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
||||||
currentPosition.x += screenWidth/2;
|
currentPosition.x += (float)screenWidth/2;
|
||||||
currentPosition.y += screenHeight/2 - 100;
|
currentPosition.y += (float)screenHeight/2 - 100;
|
||||||
|
|
||||||
// Draw to render texture
|
// Draw to render texture
|
||||||
BeginTextureMode(target);
|
BeginTextureMode(target);
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ int main(void)
|
||||||
if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0);
|
if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0);
|
||||||
else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0);
|
else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0);
|
||||||
|
|
||||||
fontPosition.x = GetScreenWidth()/2 - textSize.x/2;
|
fontPosition.x = (float)GetScreenWidth()/2 - textSize.x/2;
|
||||||
fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80;
|
fontPosition.y = (float)GetScreenHeight()/2 - textSize.y/2 + 80;
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
|
|
||||||
|
|
@ -180,12 +180,12 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float
|
||||||
if (text[i - 1] == 'c')
|
if (text[i - 1] == 'c')
|
||||||
{
|
{
|
||||||
colFront = GetColor(colHexValue);
|
colFront = GetColor(colHexValue);
|
||||||
colFront.a = (unsigned char)(colFront.a * (float)color.a/255.0f);
|
//colFront.a *= (unsigned char)(colFront.a*(float)color.a/255.0f); // TODO: Review
|
||||||
}
|
}
|
||||||
else if (text[i - 1] == 'b')
|
else if (text[i - 1] == 'b')
|
||||||
{
|
{
|
||||||
colBack = GetColor(colHexValue);
|
colBack = GetColor(colHexValue);
|
||||||
colBack.a *= (unsigned char)(colFront.a * (float)color.a / 255.0f);
|
//colBack.a *= (unsigned char)(colFront.a*(float)color.a/255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += (colHexCount + 1); // Skip color value retrieved and ']'
|
i += (colHexCount + 1); // Skip color value retrieved and ']'
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
{
|
{
|
||||||
if (!wordWrap)
|
if (!wordWrap)
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +234,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
{
|
{
|
||||||
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +258,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
|
|
||||||
if (wordWrap && (i == endLine))
|
if (wordWrap && (i == endLine))
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
startLine = endLine;
|
startLine = endLine;
|
||||||
endLine = -1;
|
endLine = -1;
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ int main(void)
|
||||||
DrawTriangle(a, b, c, emoji[selected].color);
|
DrawTriangle(a, b, c, emoji[selected].color);
|
||||||
|
|
||||||
// Draw the main text message
|
// Draw the main text message
|
||||||
Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height };
|
Rectangle textRect = { msgRect.x + (float)horizontalPadding/2, msgRect.y + (float)verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height };
|
||||||
DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE);
|
DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE);
|
||||||
|
|
||||||
// Draw the info text below the main message
|
// Draw the info text below the main message
|
||||||
|
|
@ -421,7 +421,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
{
|
{
|
||||||
if (!wordWrap)
|
if (!wordWrap)
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -429,7 +429,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
{
|
{
|
||||||
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,7 +453,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
|
|
||||||
if (wordWrap && (i == endLine))
|
if (wordWrap && (i == endLine))
|
||||||
{
|
{
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
startLine = endLine;
|
startLine = endLine;
|
||||||
endLine = -1;
|
endLine = -1;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ int main(void)
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment");
|
InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment");
|
||||||
|
|
||||||
// Define the rectangle we will draw the text in
|
// Define the rectangle we will draw the text in
|
||||||
Rectangle textContainerRect = (Rectangle){ screenWidth/2-screenWidth/4, screenHeight/2-screenHeight/3, screenWidth/2, screenHeight*2/3 };
|
Rectangle textContainerRect = (Rectangle){ (float)screenWidth/2-(float)screenWidth/4, (float)screenHeight/2-(float)screenHeight/3, (float)screenWidth/2, (float)screenHeight*2/3 };
|
||||||
|
|
||||||
// Some text to display the current alignment
|
// Some text to display the current alignment
|
||||||
const char *textAlignNameH[] = { "Left", "Centre", "Right" };
|
const char *textAlignNameH[] = { "Left", "Centre", "Right" };
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,10 @@ int main(void)
|
||||||
bunnies[i].position.x += bunnies[i].speed.x;
|
bunnies[i].position.x += bunnies[i].speed.x;
|
||||||
bunnies[i].position.y += bunnies[i].speed.y;
|
bunnies[i].position.y += bunnies[i].speed.y;
|
||||||
|
|
||||||
if (((bunnies[i].position.x + texBunny.width/2) > GetScreenWidth()) ||
|
if (((bunnies[i].position.x + (float)texBunny.width/2) > GetScreenWidth()) ||
|
||||||
((bunnies[i].position.x + texBunny.width/2) < 0)) bunnies[i].speed.x *= -1;
|
((bunnies[i].position.x + (float)texBunny.width/2) < 0)) bunnies[i].speed.x *= -1;
|
||||||
if (((bunnies[i].position.y + texBunny.height/2) > GetScreenHeight()) ||
|
if (((bunnies[i].position.y + (float)texBunny.height/2) > GetScreenHeight()) ||
|
||||||
((bunnies[i].position.y + texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1;
|
((bunnies[i].position.y + (float)texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ int main(void)
|
||||||
|
|
||||||
// If the mouse is on this preset, highlight it
|
// If the mouse is on this preset, highlight it
|
||||||
if (mouseInCell == i + 8)
|
if (mouseInCell == i + 8)
|
||||||
DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*(i/2),
|
DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*((float)i/2),
|
||||||
(presetsSizeY + 2.0f)*(i%2),
|
(presetsSizeY + 2.0f)*(i%2),
|
||||||
presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED);
|
presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,8 @@ int main(void)
|
||||||
for (unsigned int i = 0; i < map.tilesX*map.tilesY; i++) if (map.tileFog[i] == 1) map.tileFog[i] = 2;
|
for (unsigned int i = 0; i < map.tilesX*map.tilesY; i++) if (map.tileFog[i] == 1) map.tileFog[i] = 2;
|
||||||
|
|
||||||
// Get current tile position from player pixel position
|
// Get current tile position from player pixel position
|
||||||
playerTileX = (int)((playerPosition.x + MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
|
playerTileX = (int)((playerPosition.x + (float)MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
|
||||||
playerTileY = (int)((playerPosition.y + MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
|
playerTileY = (int)((playerPosition.y + (float)MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
|
||||||
|
|
||||||
// Check visibility and update fog
|
// Check visibility and update fog
|
||||||
// NOTE: We check tilemap limits to avoid processing tiles out-of-array-bounds (it could crash program)
|
// NOTE: We check tilemap limits to avoid processing tiles out-of-array-bounds (it could crash program)
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
DrawRectangleRec(toggleRecs[i], ((i == currentProcess) || (i == mouseHoverRec)) ? SKYBLUE : LIGHTGRAY);
|
DrawRectangleRec(toggleRecs[i], ((i == currentProcess) || (i == mouseHoverRec)) ? SKYBLUE : LIGHTGRAY);
|
||||||
DrawRectangleLines((int)toggleRecs[i].x, (int) toggleRecs[i].y, (int) toggleRecs[i].width, (int) toggleRecs[i].height, ((i == currentProcess) || (i == mouseHoverRec)) ? BLUE : GRAY);
|
DrawRectangleLines((int)toggleRecs[i].x, (int) toggleRecs[i].y, (int) toggleRecs[i].width, (int) toggleRecs[i].height, ((i == currentProcess) || (i == mouseHoverRec)) ? BLUE : GRAY);
|
||||||
DrawText( processText[i], (int)( toggleRecs[i].x + toggleRecs[i].width/2 - MeasureText(processText[i], 10)/2), (int) toggleRecs[i].y + 11, 10, ((i == currentProcess) || (i == mouseHoverRec)) ? DARKBLUE : DARKGRAY);
|
DrawText( processText[i], (int)( toggleRecs[i].x + toggleRecs[i].width/2 - (float)MeasureText(processText[i], 10)/2), (int) toggleRecs[i].y + 11, 10, ((i == currentProcess) || (i == mouseHoverRec)) ? DARKBLUE : DARKGRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE);
|
DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ int main(void)
|
||||||
Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM)
|
Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM)
|
||||||
UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
|
UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
|
||||||
|
|
||||||
Vector2 position = { (float)(screenWidth/2 - texture.width/2), (float)(screenHeight/2 - texture.height/2 - 20) };
|
Vector2 position = { (float)screenWidth/2 - (float)texture.width/2, (float)screenHeight/2 - (float)texture.height/2 - 20 };
|
||||||
|
|
||||||
bool showFont = false;
|
bool showFont = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ int main(void)
|
||||||
Rectangle sourceRec = { 0, 0, (float)button.width, frameHeight };
|
Rectangle sourceRec = { 0, 0, (float)button.width, frameHeight };
|
||||||
|
|
||||||
// Define button bounds on screen
|
// Define button bounds on screen
|
||||||
Rectangle btnBounds = { screenWidth/2.0f - button.width/2.0f, screenHeight/2.0f - button.height/NUM_FRAMES/2.0f, (float)button.width, frameHeight };
|
Rectangle btnBounds = { screenWidth/2.0f - button.width/2.0f, screenHeight/2.0f - (float)button.height/NUM_FRAMES/2.0f, (float)button.width, frameHeight };
|
||||||
|
|
||||||
int btnState = 0; // Button state: 0-NORMAL, 1-MOUSE_HOVER, 2-PRESSED
|
int btnState = 0; // Button state: 0-NORMAL, 1-MOUSE_HOVER, 2-PRESSED
|
||||||
bool btnAction = false; // Button action should be activated
|
bool btnAction = false; // Button action should be activated
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ int main(void)
|
||||||
Texture2D explosion = LoadTexture("resources/explosion.png");
|
Texture2D explosion = LoadTexture("resources/explosion.png");
|
||||||
|
|
||||||
// Init variables for animation
|
// Init variables for animation
|
||||||
float frameWidth = (float)(explosion.width/NUM_FRAMES_PER_LINE); // Sprite one frame rectangle width
|
float frameWidth = (float)explosion.width/NUM_FRAMES_PER_LINE; // Sprite one frame rectangle width
|
||||||
float frameHeight = (float)(explosion.height/NUM_LINES); // Sprite one frame rectangle height
|
float frameHeight = (float)explosion.height/NUM_LINES; // Sprite one frame rectangle height
|
||||||
int currentFrame = 0;
|
int currentFrame = 0;
|
||||||
int currentLine = 0;
|
int currentLine = 0;
|
||||||
|
|
||||||
|
|
|
||||||
775
src/external/miniaudio.h
vendored
775
src/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load Diff
30
src/external/rlsw.h
vendored
30
src/external/rlsw.h
vendored
|
|
@ -1177,7 +1177,7 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4])
|
||||||
static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4])
|
static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4])
|
||||||
{
|
{
|
||||||
#if defined(SW_HAS_NEON)
|
#if defined(SW_HAS_NEON)
|
||||||
uint8x8_t bytes8 = vld1_u8(src); //< Read 8 bytes, faster, but let's hope we're not at the end of the page (unlikely)...
|
uint8x8_t bytes8 = vld1_u8(src); // Reading 8 bytes, faster, but let's hope not hitting the end of the page (unlikely)...
|
||||||
uint16x8_t bytes16 = vmovl_u8(bytes8);
|
uint16x8_t bytes16 = vmovl_u8(bytes8);
|
||||||
uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16));
|
uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16));
|
||||||
float32x4_t floats = vcvtq_f32_u32(ints);
|
float32x4_t floats = vcvtq_f32_u32(ints);
|
||||||
|
|
@ -1224,8 +1224,8 @@ static inline uint32_t sw_half_to_float_ui(uint16_t h)
|
||||||
// denormal: flush to zero
|
// denormal: flush to zero
|
||||||
r = (em < (1 << 10))? 0 : r;
|
r = (em < (1 << 10))? 0 : r;
|
||||||
|
|
||||||
// infinity/NaN; note that we preserve NaN payload as a byproduct of unifying inf/nan cases
|
// NOTE: infinity/NaN; NaN payload is preserved as a byproduct of unifying inf/nan cases
|
||||||
// 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255
|
// 112 is an exponent bias fixup; since it is already applied once, applying it twice converts 31 to 255
|
||||||
r += (em >= (31 << 10))? (112 << 23) : 0;
|
r += (em >= (31 << 10))? (112 << 23) : 0;
|
||||||
|
|
||||||
return s | r;
|
return s | r;
|
||||||
|
|
@ -1252,7 +1252,7 @@ static inline uint16_t sw_half_from_float_ui(uint32_t ui)
|
||||||
// Overflow: infinity; 143 encodes exponent 16
|
// Overflow: infinity; 143 encodes exponent 16
|
||||||
h = (em >= (143 << 23))? 0x7c00 : h;
|
h = (em >= (143 << 23))? 0x7c00 : h;
|
||||||
|
|
||||||
// NaN; note that we convert all types of NaN to qNaN
|
// NOTE: NaN; all types of NaN aree converted to qNaN
|
||||||
h = (em > (255 << 23))? 0x7e00 : h;
|
h = (em > (255 << 23))? 0x7e00 : h;
|
||||||
|
|
||||||
return (uint16_t)(s | h);
|
return (uint16_t)(s | h);
|
||||||
|
|
@ -1918,8 +1918,8 @@ static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *t
|
||||||
|
|
||||||
static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v)
|
static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v)
|
||||||
{
|
{
|
||||||
// TODO: With a bit more cleverness we could clearly reduce the
|
// TODO: With a bit more cleverness thee number of operations can
|
||||||
// number of operations here, but for now it works fine
|
// be clearly reduced, but for now it works fine
|
||||||
|
|
||||||
float xf = (u*tex->width) - 0.5f;
|
float xf = (u*tex->width) - 0.5f;
|
||||||
float yf = (v*tex->height) - 0.5f;
|
float yf = (v*tex->height) - 0.5f;
|
||||||
|
|
@ -1933,7 +1933,7 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
|
||||||
int x1 = x0 + 1;
|
int x1 = x0 + 1;
|
||||||
int y1 = y0 + 1;
|
int y1 = y0 + 1;
|
||||||
|
|
||||||
// NOTE: If the textures are POT we could avoid the division for SW_REPEAT
|
// NOTE: If the textures are POT, avoid the division for SW_REPEAT
|
||||||
|
|
||||||
if (tex->sWrap == SW_CLAMP)
|
if (tex->sWrap == SW_CLAMP)
|
||||||
{
|
{
|
||||||
|
|
@ -1974,7 +1974,7 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
|
||||||
static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy)
|
static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy)
|
||||||
{
|
{
|
||||||
// Previous method: There is no need to compute the square root
|
// Previous method: There is no need to compute the square root
|
||||||
// because using the squared value, the comparison remains `L2 > 1.0f*1.0f`
|
// because using the squared value, the comparison remains (L2 > 1.0f*1.0f)
|
||||||
//float du = sqrtf(dUdx*dUdx + dUdy*dUdy);
|
//float du = sqrtf(dUdx*dUdx + dUdy*dUdy);
|
||||||
//float dv = sqrtf(dVdx*dVdx + dVdy*dVdy);
|
//float dv = sqrtf(dVdx*dVdx + dVdy*dVdy);
|
||||||
//float L = (du > dv)? du : dv;
|
//float L = (du > dv)? du : dv;
|
||||||
|
|
@ -2205,7 +2205,7 @@ static inline bool sw_triangle_face_culling(void)
|
||||||
{
|
{
|
||||||
// NOTE: Face culling is done before clipping to avoid unnecessary computations
|
// NOTE: Face culling is done before clipping to avoid unnecessary computations
|
||||||
// To handle triangles crossing the w=0 plane correctly,
|
// To handle triangles crossing the w=0 plane correctly,
|
||||||
// we perform the winding order test in homogeneous coordinates directly,
|
// the winding order test is performeed in homogeneous coordinates directly,
|
||||||
// before the perspective division (division by w)
|
// before the perspective division (division by w)
|
||||||
// This test determines the orientation of the triangle in the (x,y,w) plane,
|
// This test determines the orientation of the triangle in the (x,y,w) plane,
|
||||||
// which corresponds to the projected 2D winding order sign,
|
// which corresponds to the projected 2D winding order sign,
|
||||||
|
|
@ -2559,11 +2559,11 @@ static inline bool sw_quad_face_culling(void)
|
||||||
{
|
{
|
||||||
// NOTE: Face culling is done before clipping to avoid unnecessary computations
|
// NOTE: Face culling is done before clipping to avoid unnecessary computations
|
||||||
// To handle quads crossing the w=0 plane correctly,
|
// To handle quads crossing the w=0 plane correctly,
|
||||||
// we perform the winding order test in homogeneous coordinates directly,
|
// the winding order test is performed in homogeneous coordinates directly,
|
||||||
// before the perspective division (division by w)
|
// before the perspective division (division by w)
|
||||||
// For a convex quad with vertices P0, P1, P2, P3 in sequential order,
|
// For a convex quad with vertices P0, P1, P2, P3 in sequential order,
|
||||||
// the winding order of the quad is the same as the winding order
|
// the winding order of the quad is the same as the winding order
|
||||||
// of the triangle P0 P1 P2. We use the homogeneous triangle
|
// of the triangle P0 P1 P2. The homogeneous triangle is used on
|
||||||
// winding test on this first triangle
|
// winding test on this first triangle
|
||||||
|
|
||||||
// Preload homogeneous coordinates into local variables
|
// Preload homogeneous coordinates into local variables
|
||||||
|
|
@ -2649,7 +2649,7 @@ static inline bool sw_quad_is_axis_aligned(void)
|
||||||
{
|
{
|
||||||
// Reject quads with perspective projection
|
// Reject quads with perspective projection
|
||||||
// The fast path assumes affine (non-perspective) quads,
|
// The fast path assumes affine (non-perspective) quads,
|
||||||
// so we require all vertices to have homogeneous w = 1.0
|
// so it's required for all vertices to have homogeneous w = 1.0
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
|
if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
|
||||||
|
|
@ -2721,7 +2721,7 @@ static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
|
||||||
|
|
||||||
// TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
|
// TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
|
||||||
// still appear perfectly aligned from a certain point of view?
|
// still appear perfectly aligned from a certain point of view?
|
||||||
// Because in that case, we would still need to perform perspective division for textures and colors...
|
// Because in that case, it's still needed to perform perspective division for textures and colors...
|
||||||
#define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
|
#define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
|
||||||
static inline void FUNC_NAME(void) \
|
static inline void FUNC_NAME(void) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -3090,7 +3090,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \
|
||||||
\
|
\
|
||||||
for (int i = 0; i < numPixels; i++) \
|
for (int i = 0; i < numPixels; i++) \
|
||||||
{ \
|
{ \
|
||||||
/* REVIEW: May require reviewing projection details */ \
|
/* TODO: REVIEW: May require reviewing projection details */ \
|
||||||
int px = (int)(x - 0.5f); \
|
int px = (int)(x - 0.5f); \
|
||||||
int py = (int)(y - 0.5f); \
|
int py = (int)(y - 0.5f); \
|
||||||
\
|
\
|
||||||
|
|
@ -3721,7 +3721,7 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
|
||||||
ySrc = sw_clampi(ySrc, 0, hSrc);
|
ySrc = sw_clampi(ySrc, 0, hSrc);
|
||||||
|
|
||||||
// Check if the sizes are identical after clamping the source to avoid unexpected issues
|
// Check if the sizes are identical after clamping the source to avoid unexpected issues
|
||||||
// REVIEW: This repeats the operations if true, so we could make a copy function without these checks
|
// TODO: REVIEW: This repeats the operations if true, so a copy function can be made without these checks
|
||||||
if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
|
if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
|
||||||
{
|
{
|
||||||
swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
|
swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
|
||||||
|
|
|
||||||
|
|
@ -1189,7 +1189,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
||||||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
|
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
|
||||||
{
|
{
|
||||||
// For now we'll assume a single gamepad which we "detect" on its input event
|
// Assuming a single gamepad, "detected" on its input event
|
||||||
CORE.Input.Gamepad.ready[0] = true;
|
CORE.Input.Gamepad.ready[0] = true;
|
||||||
|
|
||||||
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_X] = AMotionEvent_getAxisValue(
|
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_X] = AMotionEvent_getAxisValue(
|
||||||
|
|
@ -1256,7 +1256,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
|
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
|
||||||
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
|
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
|
||||||
{
|
{
|
||||||
// For now we'll assume a single gamepad which we "detect" on its input event
|
// Assuming a single gamepad, "detected" on its input event
|
||||||
CORE.Input.Gamepad.ready[0] = true;
|
CORE.Input.Gamepad.ready[0] = true;
|
||||||
|
|
||||||
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
||||||
|
|
|
||||||
|
|
@ -602,7 +602,7 @@ void SetWindowIcon(Image image)
|
||||||
icon[0].height = image.height;
|
icon[0].height = image.height;
|
||||||
icon[0].pixels = (unsigned char *)image.data;
|
icon[0].pixels = (unsigned char *)image.data;
|
||||||
|
|
||||||
// NOTE 1: We only support one image icon
|
// NOTE 1: Only one image icon supported
|
||||||
// NOTE 2: The specified image data is copied before this function returns
|
// NOTE 2: The specified image data is copied before this function returns
|
||||||
glfwSetWindowIcon(platform.handle, 1, icon);
|
glfwSetWindowIcon(platform.handle, 1, icon);
|
||||||
}
|
}
|
||||||
|
|
@ -833,7 +833,7 @@ int GetCurrentMonitor(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// In case the window is between two monitors, we use below logic
|
// In case the window is between two monitors, below logic is used
|
||||||
// to try to detect the "current monitor" for that window, note that
|
// to try to detect the "current monitor" for that window, note that
|
||||||
// this is probably an overengineered solution for a very side case
|
// this is probably an overengineered solution for a very side case
|
||||||
// trying to match SDL behaviour
|
// trying to match SDL behaviour
|
||||||
|
|
@ -1186,7 +1186,7 @@ void SetMouseCursor(int cursor)
|
||||||
if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);
|
if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: We are relating internal GLFW enum values to our MouseCursor enum values
|
// NOTE: Mapping internal GLFW enum values to MouseCursor enum values
|
||||||
glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));
|
glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1211,7 +1211,7 @@ void PollInputEvents(void)
|
||||||
CORE.Input.Keyboard.charPressedQueueCount = 0;
|
CORE.Input.Keyboard.charPressedQueueCount = 0;
|
||||||
|
|
||||||
// Reset last gamepad button/axis registered state
|
// Reset last gamepad button/axis registered state
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
|
||||||
//CORE.Input.Gamepad.axisCount = 0;
|
//CORE.Input.Gamepad.axisCount = 0;
|
||||||
|
|
||||||
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
|
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
|
||||||
|
|
@ -1247,7 +1247,7 @@ void PollInputEvents(void)
|
||||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
// Check if gamepads are ready
|
// Check if gamepads are ready
|
||||||
// NOTE: We do it here in case of disconnection
|
// NOTE: Doing it here in case of disconnection
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;
|
if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;
|
||||||
|
|
@ -1263,7 +1263,7 @@ void PollInputEvents(void)
|
||||||
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
|
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
|
||||||
|
|
||||||
// Get current gamepad state
|
// Get current gamepad state
|
||||||
// NOTE: There is no callback available, so we get it manually
|
// NOTE: There is no callback available, getting it manually
|
||||||
GLFWgamepadstate state = { 0 };
|
GLFWgamepadstate state = { 0 };
|
||||||
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
|
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
|
||||||
if (result == GLFW_FALSE) // No joystick is connected, no gamepad mapping or an error occurred
|
if (result == GLFW_FALSE) // No joystick is connected, no gamepad mapping or an error occurred
|
||||||
|
|
@ -1359,8 +1359,8 @@ void PollInputEvents(void)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
|
// Function wrappers around RL_*ALLOC macros, used by glfwInitAllocator() inside of InitPlatform()
|
||||||
// We need to provide these because GLFWallocator expects function pointers with specific signatures
|
// GLFWallocator expects function pointers with specific signatures to be provided
|
||||||
// REF: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
// REF: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
||||||
static void *AllocateWrapper(size_t size, void *user)
|
static void *AllocateWrapper(size_t size, void *user)
|
||||||
{
|
{
|
||||||
|
|
@ -1742,7 +1742,7 @@ int InitPlatform(void)
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||||
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
|
// only copying up to (MAX_GAMEPAD_NAME_LENGTH - 1)
|
||||||
if (glfwJoystickPresent(i))
|
if (glfwJoystickPresent(i))
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.ready[i] = true;
|
CORE.Input.Gamepad.ready[i] = true;
|
||||||
|
|
@ -1819,8 +1819,8 @@ static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
|
||||||
{
|
{
|
||||||
//TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
|
//TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
|
||||||
|
|
||||||
// WARNING: On window minimization, callback is called,
|
// WARNING: On window minimization, callback is called with 0 values,
|
||||||
// but we don't want to change internal screen values, it breaks things
|
// but internal screen values should not be changed, it breaks things
|
||||||
if ((width == 0) || (height == 0)) return;
|
if ((width == 0) || (height == 0)) return;
|
||||||
|
|
||||||
// Reset viewport and projection matrix for new size
|
// Reset viewport and projection matrix for new size
|
||||||
|
|
@ -1926,7 +1926,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
// In case previous dropped filepaths have not been freed, we free them
|
// In case previous dropped filepaths have not been freed, free them
|
||||||
if (CORE.Window.dropFileCount > 0)
|
if (CORE.Window.dropFileCount > 0)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
||||||
|
|
@ -1937,7 +1937,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
CORE.Window.dropFilepaths = NULL;
|
CORE.Window.dropFilepaths = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
|
// WARNING: Paths are freed by GLFW when the callback returns, keeping an internal copy
|
||||||
CORE.Window.dropFileCount = count;
|
CORE.Window.dropFileCount = count;
|
||||||
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
||||||
|
|
||||||
|
|
@ -1954,7 +1954,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
{
|
{
|
||||||
if (key < 0) return; // Security check, macOS fn key generates -1
|
if (key < 0) return; // Security check, macOS fn key generates -1
|
||||||
|
|
||||||
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
// WARNING: GLFW could return GLFW_REPEAT, it needs to be considered as 1
|
||||||
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
||||||
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
||||||
else if (action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
|
else if (action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
|
||||||
|
|
@ -2079,7 +2079,7 @@ static void JoystickCallback(int jid, int event)
|
||||||
if (event == GLFW_CONNECTED)
|
if (event == GLFW_CONNECTED)
|
||||||
{
|
{
|
||||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||||
// we can get a not-NULL terminated string, so, we clean destination and only copy up to -1
|
// only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string
|
||||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||||
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
#define USING_SDL3_PROJECT
|
#define USING_SDL3_PROJECT
|
||||||
#endif
|
#endif
|
||||||
#ifndef SDL_ENABLE_OLD_NAMES
|
#ifndef SDL_ENABLE_OLD_NAMES
|
||||||
#define SDL_ENABLE_OLD_NAMES // Just in case we're on SDL3, we need some in-between compatibily
|
#define SDL_ENABLE_OLD_NAMES // Just in case on SDL3, some in-between compatibily is needed
|
||||||
#endif
|
#endif
|
||||||
// SDL base library (window/rendered, input, timing... functionality)
|
// SDL base library (window/rendered, input, timing... functionality)
|
||||||
#ifdef USING_SDL3_PROJECT
|
#ifdef USING_SDL3_PROJECT
|
||||||
|
|
@ -340,8 +340,7 @@ SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDL3 Migration:
|
// SDL3 Migration:
|
||||||
// SDL_GetDisplayDPI() -
|
// SDL_GetDisplayDPI() not reliable across platforms, approximately replaced by multiplying
|
||||||
// not reliable across platforms, approximately replaced by multiplying
|
|
||||||
// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms
|
// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms
|
||||||
// returns 0 on success or a negative error code on failure
|
// returns 0 on success or a negative error code on failure
|
||||||
int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi)
|
int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi)
|
||||||
|
|
@ -413,7 +412,7 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // We're on SDL2
|
#else // SDL2 fallback
|
||||||
|
|
||||||
// Since SDL2 doesn't have this function we leave a stub
|
// Since SDL2 doesn't have this function we leave a stub
|
||||||
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
|
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
|
||||||
|
|
@ -833,10 +832,9 @@ void SetWindowMonitor(int monitor)
|
||||||
if ((monitor >= 0) && (monitor < monitorCount))
|
if ((monitor >= 0) && (monitor < monitorCount))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// NOTE:
|
// NOTE 1: SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
|
||||||
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
|
|
||||||
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
|
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
|
||||||
// 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again
|
// NOTE 2: A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again
|
||||||
const bool wasFullscreen = (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))? true : false;
|
const bool wasFullscreen = (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))? true : false;
|
||||||
|
|
||||||
const int screenWidth = CORE.Window.screen.width;
|
const int screenWidth = CORE.Window.screen.width;
|
||||||
|
|
@ -854,13 +852,12 @@ void SetWindowMonitor(int monitor)
|
||||||
// If the screen size is larger than the monitor usable area, anchor it on the top left corner, otherwise, center it
|
// If the screen size is larger than the monitor usable area, anchor it on the top left corner, otherwise, center it
|
||||||
if ((screenWidth >= usableBounds.w) || (screenHeight >= usableBounds.h))
|
if ((screenWidth >= usableBounds.w) || (screenHeight >= usableBounds.h))
|
||||||
{
|
{
|
||||||
// NOTE:
|
// NOTE 1: There's a known issue where if the window larger than the target display bounds,
|
||||||
// 1. There's a known issue where if the window larger than the target display bounds,
|
|
||||||
// when moving the windows to that display, the window could be clipped back
|
// when moving the windows to that display, the window could be clipped back
|
||||||
// ending up positioned partly outside the target display
|
// ending up positioned partly outside the target display
|
||||||
// 2. The workaround for that is, previously to moving the window,
|
// NOTE 2: The workaround for that is, previously to moving the window,
|
||||||
// setting the window size to the target display size, so they match
|
// setting the window size to the target display size, so they match
|
||||||
// 3. It wasn't done here because we can't assume changing the window size automatically
|
// NOTE 3: It wasn't done here because we can't assume changing the window size automatically
|
||||||
// is acceptable behavior by the user
|
// is acceptable behavior by the user
|
||||||
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
|
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
|
||||||
CORE.Window.position.x = usableBounds.x;
|
CORE.Window.position.x = usableBounds.x;
|
||||||
|
|
@ -1250,7 +1247,7 @@ void DisableCursor(void)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
|
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
|
||||||
// NOTE: We use a preprocessor condition here because `rlCopyFramebuffer` is only declared for software rendering
|
// NOTE: We use a preprocessor condition here because rlCopyFramebuffer() is only declared for software rendering
|
||||||
SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
|
SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
|
||||||
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
|
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
|
||||||
SDL_UpdateWindowSurface(platform.window);
|
SDL_UpdateWindowSurface(platform.window);
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ static bool UpdateWindowSize(int mode, HWND hwnd, int width, int height, unsigne
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify if we are running in Windows 10 version 1703 (Creators Update)
|
// Check if running in Windows 10 version 1703 (Creators Update)
|
||||||
static BOOL IsWindows10Version1703OrGreaterWin32(void)
|
static BOOL IsWindows10Version1703OrGreaterWin32(void)
|
||||||
{
|
{
|
||||||
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
|
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
|
||||||
|
|
@ -1138,7 +1138,7 @@ void ShowCursor(void)
|
||||||
// Hides mouse cursor
|
// Hides mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
// NOTE: We use SetCursor() instead of ShowCursor() because
|
// NOTE: Using SetCursor() instead of ShowCursor() because
|
||||||
// it makes it easy to only hide the cursor while it's inside the client area
|
// it makes it easy to only hide the cursor while it's inside the client area
|
||||||
SetCursor(NULL);
|
SetCursor(NULL);
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
|
|
@ -1227,7 +1227,7 @@ void SwapScreenBuffer(void)
|
||||||
// Get elapsed time measure in seconds
|
// Get elapsed time measure in seconds
|
||||||
double GetTime(void)
|
double GetTime(void)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER now = 0;
|
LARGE_INTEGER now = { 0 };
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(&now);
|
||||||
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
@ -1345,7 +1345,7 @@ void PollInputEvents(void)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize modern OpenGL context
|
// Initialize modern OpenGL context
|
||||||
// NOTE: We need to create a dummy context first to query required extensions
|
// NOTE: Creating a dummy context first to query required extensions
|
||||||
HGLRC InitOpenGL(HWND hwnd, HDC hdc)
|
HGLRC InitOpenGL(HWND hwnd, HDC hdc)
|
||||||
{
|
{
|
||||||
// First, create a dummy context to get WGL extensions
|
// First, create a dummy context to get WGL extensions
|
||||||
|
|
@ -1460,7 +1460,7 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
|
||||||
0 // Terminator
|
0 // Terminator
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: We are not sharing context resources so, second parameters is NULL
|
// NOTE: Not sharing context resources so, second parameters is NULL
|
||||||
realContext = wglCreateContextAttribsARB(hdc, NULL, contextAttribs);
|
realContext = wglCreateContextAttribsARB(hdc, NULL, contextAttribs);
|
||||||
|
|
||||||
// Check for error context creation errors
|
// Check for error context creation errors
|
||||||
|
|
@ -1476,8 +1476,8 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
|
||||||
// Activate real context
|
// Activate real context
|
||||||
if (realContext) wglMakeCurrent(hdc, realContext);
|
if (realContext) wglMakeCurrent(hdc, realContext);
|
||||||
|
|
||||||
// Once we got a real modern OpenGL context,
|
// Once a real modern OpenGL context is created,
|
||||||
// we can load required extensions (function pointers)
|
// required extensions can be loaded (function pointers)
|
||||||
rlLoadExtensions(WglGetProcAddress);
|
rlLoadExtensions(WglGetProcAddress);
|
||||||
|
|
||||||
return realContext;
|
return realContext;
|
||||||
|
|
@ -1521,7 +1521,7 @@ int InitPlatform(void)
|
||||||
.lpfnWndProc = WndProc, // Custom procedure assigned
|
.lpfnWndProc = WndProc, // Custom procedure assigned
|
||||||
.cbWndExtra = sizeof(LONG_PTR), // extra space for the Tuple object ptr
|
.cbWndExtra = sizeof(LONG_PTR), // extra space for the Tuple object ptr
|
||||||
.hInstance = hInstance,
|
.hInstance = hInstance,
|
||||||
.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW), // TODO: Audit if we want to set this since we're implementing WM_SETCURSOR
|
.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW), // TODO: Check if this is really required, since WM_SETCURSOR event is processed
|
||||||
.lpszClassName = CLASS_NAME // Class name: L"raylibWindow"
|
.lpszClassName = CLASS_NAME // Class name: L"raylibWindow"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1854,8 +1854,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
||||||
SIZE *inoutSize = (SIZE *)lparam;
|
SIZE *inoutSize = (SIZE *)lparam;
|
||||||
UINT newDpi = (UINT)wparam; // TODO: WARNING: Converting from WPARAM = UINT_PTR
|
UINT newDpi = (UINT)wparam; // TODO: WARNING: Converting from WPARAM = UINT_PTR
|
||||||
|
|
||||||
// for any of these other cases, we might want to post a window
|
// For the following flag changes, a window resize event should be posted,
|
||||||
// resize event after the dpi changes?
|
// TODO: Should it be done after dpi changes?
|
||||||
if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return TRUE;
|
if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return TRUE;
|
||||||
if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) return TRUE;
|
if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) return TRUE;
|
||||||
if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) return TRUE;
|
if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) return TRUE;
|
||||||
|
|
@ -1875,8 +1875,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
||||||
case WM_DPICHANGED:
|
case WM_DPICHANGED:
|
||||||
{
|
{
|
||||||
// Get current dpi scale factor
|
// Get current dpi scale factor
|
||||||
float scalex = HIWORD(wParam)/96.0f;
|
float scalex = HIWORD(wparam)/96.0f;
|
||||||
float scaley = LOWORD(wParam)/96.0f;
|
float scaley = LOWORD(wparam)/96.0f;
|
||||||
|
|
||||||
RECT *suggestedRect = (RECT *)lparam;
|
RECT *suggestedRect = (RECT *)lparam;
|
||||||
|
|
||||||
|
|
@ -2025,8 +2025,8 @@ static void HandleRawInput(LPARAM lparam)
|
||||||
|
|
||||||
if (input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) TRACELOG(LOG_ERROR, "TODO: handle virtual desktop mouse inputs!");
|
if (input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) TRACELOG(LOG_ERROR, "TODO: handle virtual desktop mouse inputs!");
|
||||||
|
|
||||||
// Trick to keep the mouse position at 0,0 and instead move
|
// Trick to keep the mouse position at (0,0) and instead move
|
||||||
// the previous position so we can still get a proper mouse delta
|
// the previous position so a proper mouse delta can still be retrieved
|
||||||
//CORE.Input.Mouse.previousPosition.x -= input.data.mouse.lLastX;
|
//CORE.Input.Mouse.previousPosition.x -= input.data.mouse.lLastX;
|
||||||
//CORE.Input.Mouse.previousPosition.y -= input.data.mouse.lLastY;
|
//CORE.Input.Mouse.previousPosition.y -= input.data.mouse.lLastY;
|
||||||
//if (CORE.Input.Mouse.currentPosition.x != 0) abort();
|
//if (CORE.Input.Mouse.currentPosition.x != 0) abort();
|
||||||
|
|
@ -2138,12 +2138,12 @@ static unsigned SanitizeFlags(int mode, unsigned flags)
|
||||||
// This design takes care of many odd corner cases. For example, if you want to restore
|
// This design takes care of many odd corner cases. For example, if you want to restore
|
||||||
// a window that was previously maximized AND minimized and you want to remove both these
|
// a window that was previously maximized AND minimized and you want to remove both these
|
||||||
// flags, you actually need to call ShowWindow with SW_RESTORE twice. Another example is
|
// flags, you actually need to call ShowWindow with SW_RESTORE twice. Another example is
|
||||||
// if you have a maximized window, if the undecorated flag is modified then we'd need to
|
// if you have a maximized window, if the undecorated flag is modified then the window style
|
||||||
// update the window style, but updating the style would mean the window size would change
|
// needs to be updated, but updating the style would mean the window size would change
|
||||||
// causing the window to lose its Maximized state which would mean we'd need to update the
|
// causing the window to lose its Maximized state which would mean the window size
|
||||||
// window size and then update the window style a second time to restore that maximized
|
// needs to be updated, followed by the update of window style, a second time, to restore that maximized
|
||||||
// state. This implementation is able to handle any/all of these special situations with a
|
// state. This implementation is able to handle any/all of these special situations with a
|
||||||
// retry loop that continues until we either reach the desired state or the state stops changing
|
// retry loop that continues until either the desired state is reached or the state stops changing
|
||||||
static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height)
|
static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height)
|
||||||
{
|
{
|
||||||
// Flags that just apply immediately without needing any operations
|
// Flags that just apply immediately without needing any operations
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,7 @@ int InitPlatform(void)
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
// If everything work as expected, we can continue
|
// If everything worked as expected, continue
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
|
|
|
||||||
|
|
@ -316,15 +316,16 @@ void ToggleBorderlessWindowed(void)
|
||||||
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
|
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
|
||||||
EM_ASM
|
EM_ASM
|
||||||
(
|
(
|
||||||
|
const canvasId = UTF8ToString($0);
|
||||||
setTimeout(function()
|
setTimeout(function()
|
||||||
{
|
{
|
||||||
Module.requestFullscreen(false, true);
|
Module.requestFullscreen(false, true);
|
||||||
setTimeout(function()
|
setTimeout(function()
|
||||||
{
|
{
|
||||||
canvas.style.width="unset";
|
document.querySelector(canvasId).style.width="unset";
|
||||||
}, 100);
|
}, 100);
|
||||||
}, 100);
|
}, 100);
|
||||||
);
|
, platform.canvasId);
|
||||||
FLAG_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
|
FLAG_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -953,7 +954,7 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||||
if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME;
|
if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME;
|
||||||
duration *= 1000.0f; // Convert duration to ms
|
duration *= 1000.0f; // Convert duration to ms
|
||||||
|
|
||||||
// Note: At the moment (2024.10.21) Chrome, Edge, Opera, Safari, Android Chrome, Android Webview only support the vibrationActuator API,
|
// NOTE: At the moment (2024.10.21) Chrome, Edge, Opera, Safari, Android Chrome, Android Webview only support the vibrationActuator API,
|
||||||
// and Firefox only supports the hapticActuators API
|
// and Firefox only supports the hapticActuators API
|
||||||
EM_ASM({
|
EM_ASM({
|
||||||
try
|
try
|
||||||
|
|
@ -1238,9 +1239,9 @@ int InitPlatform(void)
|
||||||
// Avoid creating a WebGL canvas, avoid calling glfwCreateWindow()
|
// Avoid creating a WebGL canvas, avoid calling glfwCreateWindow()
|
||||||
emscripten_set_canvas_element_size(platform.canvasId, CORE.Window.screen.width, CORE.Window.screen.height);
|
emscripten_set_canvas_element_size(platform.canvasId, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
EM_ASM({
|
EM_ASM({
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.querySelector(UTF8ToString($0));
|
||||||
Module.canvas = canvas;
|
Module.canvas = canvas;
|
||||||
});
|
}, platform.canvasId);
|
||||||
|
|
||||||
// Load memory framebuffer with desired screen size
|
// Load memory framebuffer with desired screen size
|
||||||
// NOTE: Despite using a software framebuffer for blitting, GLFW still creates a WebGL canvas,
|
// NOTE: Despite using a software framebuffer for blitting, GLFW still creates a WebGL canvas,
|
||||||
|
|
@ -1798,8 +1799,8 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
||||||
// Emscripten: Called on fullscreen change events
|
// Emscripten: Called on fullscreen change events
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
||||||
{
|
{
|
||||||
// NOTE: 1. Reset the fullscreen flags if the user left fullscreen manually by pressing the Escape key
|
// NOTE 1: Reset the fullscreen flags if the user left fullscreen manually by pressing the Escape key
|
||||||
// 2. Which is a necessary safeguard because that case will bypass the toggles CORE.Window.flags resets
|
// NOTE 2: Which is a necessary safeguard because that case will bypass the toggles CORE.Window.flags resets
|
||||||
if (platform.ourFullscreen) platform.ourFullscreen = false;
|
if (platform.ourFullscreen) platform.ourFullscreen = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ bool WindowShouldClose(void)
|
||||||
// and encapsulating one frame execution on a UpdateDrawFrame() function,
|
// and encapsulating one frame execution on a UpdateDrawFrame() function,
|
||||||
// allowing the browser to manage execution asynchronously
|
// allowing the browser to manage execution asynchronously
|
||||||
|
|
||||||
// Optionally we can manage the time we give-control-back-to-browser if required,
|
// NOTE: Optionally, time can be managed, giving control back-to-browser as required,
|
||||||
// but it seems below line could generate stuttering on some browsers
|
// but it seems below line could generate stuttering on some browsers
|
||||||
emscripten_sleep(12);
|
emscripten_sleep(12);
|
||||||
|
|
||||||
|
|
@ -280,15 +280,16 @@ void ToggleBorderlessWindowed(void)
|
||||||
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
|
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
|
||||||
EM_ASM
|
EM_ASM
|
||||||
(
|
(
|
||||||
|
const canvasId = UTF8ToString($0);
|
||||||
setTimeout(function()
|
setTimeout(function()
|
||||||
{
|
{
|
||||||
Module.requestFullscreen(false, true);
|
Module.requestFullscreen(false, true);
|
||||||
setTimeout(function()
|
setTimeout(function()
|
||||||
{
|
{
|
||||||
canvas.style.width="unset";
|
document.querySelector(canvasId).style.width="unset";
|
||||||
}, 100);
|
}, 100);
|
||||||
}, 100);
|
}, 100);
|
||||||
);
|
, platform.canvasId);
|
||||||
FLAG_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
|
FLAG_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1358,7 +1359,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
// In case previous dropped filepaths have not been freed, we free them
|
// In case previous dropped filepaths have not been freed, free them
|
||||||
if (CORE.Window.dropFileCount > 0)
|
if (CORE.Window.dropFileCount > 0)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
||||||
|
|
@ -1369,7 +1370,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
CORE.Window.dropFilepaths = NULL;
|
CORE.Window.dropFilepaths = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
|
// WARNING: Paths are freed by GLFW when the callback returns, an internal copy should be kept
|
||||||
CORE.Window.dropFileCount = count;
|
CORE.Window.dropFileCount = count;
|
||||||
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
||||||
|
|
||||||
|
|
@ -1610,7 +1611,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
||||||
double canvasWidth = 0.0;
|
double canvasWidth = 0.0;
|
||||||
double canvasHeight = 0.0;
|
double canvasHeight = 0.0;
|
||||||
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
||||||
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
// looking for actual CSS size: canvas.style.width and canvas.style.height
|
||||||
// EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
// EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
emscripten_get_element_css_size(platform.canvasId, &canvasWidth, &canvasHeight);
|
emscripten_get_element_css_size(platform.canvasId, &canvasWidth, &canvasHeight);
|
||||||
|
|
||||||
|
|
@ -1630,7 +1631,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update mouse position if we detect a single touch
|
// Update mouse position if a single touch is detected
|
||||||
if (CORE.Input.Touch.pointCount == 1)
|
if (CORE.Input.Touch.pointCount == 1)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentPosition.x = CORE.Input.Touch.position[0].x;
|
CORE.Input.Mouse.currentPosition.x = CORE.Input.Touch.position[0].x;
|
||||||
|
|
|
||||||
18
src/raudio.c
18
src/raudio.c
|
|
@ -2418,7 +2418,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
|
||||||
audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames;
|
audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames;
|
||||||
framesRead += framesToRead;
|
framesRead += framesToRead;
|
||||||
|
|
||||||
// If we've read to the end of the buffer, mark it as processed
|
// If the end of the buffer is read, mark it as processed
|
||||||
if (framesToRead == framesRemainingInOutputBuffer)
|
if (framesToRead == framesRemainingInOutputBuffer)
|
||||||
{
|
{
|
||||||
audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
|
audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
|
||||||
|
|
@ -2426,7 +2426,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
|
||||||
|
|
||||||
currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
|
currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
|
||||||
|
|
||||||
// We need to break from this loop if we're not looping
|
// Break from this loop if looping not enabled
|
||||||
if (!audioBuffer->looping)
|
if (!audioBuffer->looping)
|
||||||
{
|
{
|
||||||
StopAudioBufferInLockedState(audioBuffer);
|
StopAudioBufferInLockedState(audioBuffer);
|
||||||
|
|
@ -2453,10 +2453,12 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
|
||||||
// Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing
|
// Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing
|
||||||
static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount)
|
static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount)
|
||||||
{
|
{
|
||||||
// What's going on here is that we're continuously converting data from the AudioBuffer's internal format to the mixing format, which
|
// NOTE: Continuously converting data from the AudioBuffer's internal format to the mixing format,
|
||||||
// should be defined by the output format of the data converter. We do this until frameCount frames have been output. The important
|
// which should be defined by the output format of the data converter.
|
||||||
// detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output
|
// This is done until frameCount frames have been output.
|
||||||
// frames. This can be achieved with ma_data_converter_get_required_input_frame_count()
|
// The important detail to remember is that more data than required should neeveer be read,
|
||||||
|
// for the specified number of output frames.
|
||||||
|
// This can be achieved with ma_data_converter_get_required_input_frame_count()
|
||||||
ma_uint8 inputBuffer[4096] = { 0 };
|
ma_uint8 inputBuffer[4096] = { 0 };
|
||||||
ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
|
ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
|
||||||
|
|
||||||
|
|
@ -2573,8 +2575,8 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If for some reason we weren't able to read every frame we'll need to break from the loop
|
// If for some reason is not possible to read every frame, the loop needs to be broken
|
||||||
// Not doing this could theoretically put us into an infinite loop
|
// Not doing this could theoretically eend up into an infinite loop
|
||||||
if (framesToRead > 0) break;
|
if (framesToRead > 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -512,7 +512,6 @@ typedef struct VrStereoConfig {
|
||||||
|
|
||||||
// File path list
|
// File path list
|
||||||
typedef struct FilePathList {
|
typedef struct FilePathList {
|
||||||
unsigned int capacity; // Filepaths max entries
|
|
||||||
unsigned int count; // Filepaths entries count
|
unsigned int count; // Filepaths entries count
|
||||||
char **paths; // Filepaths entries
|
char **paths; // Filepaths entries
|
||||||
} FilePathList;
|
} FilePathList;
|
||||||
|
|
@ -1152,6 +1151,8 @@ RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload fi
|
||||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||||
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
|
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
|
||||||
|
RLAPI unsigned int GetDirectoryFileCount(const char *dirPath); // Get the file count in a directory
|
||||||
|
RLAPI unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs);// Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
||||||
|
|
||||||
// Compression/Encoding functionality
|
// Compression/Encoding functionality
|
||||||
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
|
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,11 @@
|
||||||
// Function specifiers definition
|
// Function specifiers definition
|
||||||
#if defined(RAYMATH_IMPLEMENTATION)
|
#if defined(RAYMATH_IMPLEMENTATION)
|
||||||
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
|
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll)
|
#define RMAPI __declspec(dllexport) extern inline // Building raylib as a Win32 shared library (.dll)
|
||||||
#elif defined(BUILD_LIBTYPE_SHARED)
|
#elif defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib)
|
#define RMAPI __attribute__((visibility("default"))) // Building raylib as a Unix shared library (.so/.dylib)
|
||||||
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
|
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
|
||||||
#define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
#define RMAPI __declspec(dllimport) // Using raylib as a Win32 shared library (.dll)
|
||||||
#else
|
#else
|
||||||
#define RMAPI extern inline // Provide external definition
|
#define RMAPI extern inline // Provide external definition
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1083,7 +1083,7 @@ RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Projects a Vector3 from screen space into object space
|
// Projects a Vector3 from screen space into object space
|
||||||
// NOTE: We are avoiding calling other raymath functions despite available
|
// NOTE: Self-contained function, no other raymath functions are called
|
||||||
RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
|
RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
|
||||||
{
|
{
|
||||||
Vector3 result = { 0 };
|
Vector3 result = { 0 };
|
||||||
|
|
@ -2369,7 +2369,7 @@ RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)
|
||||||
result.x = cross.x;
|
result.x = cross.x;
|
||||||
result.y = cross.y;
|
result.y = cross.y;
|
||||||
result.z = cross.z;
|
result.z = cross.z;
|
||||||
result.w = 1.0f + cos2Theta;
|
result.w = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z + cos2Theta*cos2Theta) + cos2Theta;
|
||||||
|
|
||||||
// QuaternionNormalize(q);
|
// QuaternionNormalize(q);
|
||||||
// NOTE: Normalize to essentially nlerp the original and identity to 0.5
|
// NOTE: Normalize to essentially nlerp the original and identity to 0.5
|
||||||
|
|
|
||||||
265
src/rcore.c
265
src/rcore.c
|
|
@ -267,9 +267,15 @@
|
||||||
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DIRECTORY_FILTER_TAG
|
#ifndef FILE_FILTER_TAG_ALL
|
||||||
#define DIRECTORY_FILTER_TAG "DIR" // Name tag used to request directory inclusion on directory scan
|
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx()
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||||
|
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
||||||
|
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan
|
||||||
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||||
|
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
||||||
|
#define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan
|
||||||
|
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||||
|
|
||||||
// Flags operation macros
|
// Flags operation macros
|
||||||
#define FLAG_SET(n, f) ((n) |= (f))
|
#define FLAG_SET(n, f) ((n) |= (f))
|
||||||
|
|
@ -505,8 +511,7 @@ extern void ClosePlatform(void); // Close platform
|
||||||
static void InitTimer(void); // Initialize timer, hi-resolution if available (required by InitPlatform())
|
static void InitTimer(void); // Initialize timer, hi-resolution if available (required by InitPlatform())
|
||||||
static void SetupViewport(int width, int height); // Set viewport for a provided width and height
|
static void SetupViewport(int width, int height); // Set viewport for a provided width and height
|
||||||
|
|
||||||
static void ScanDirectoryFiles(const char *basePath, FilePathList *list, const char *filter); // Scan all files and directories in a base path
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *list, const char *filter, unsigned int expectedFileCount, bool scanSubdirs); // Scan all files and directories in a base path
|
||||||
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *list, const char *filter); // Scan all files and directories recursively from a base path
|
|
||||||
|
|
||||||
#if defined(SUPPORT_AUTOMATION_EVENTS)
|
#if defined(SUPPORT_AUTOMATION_EVENTS)
|
||||||
static void RecordAutomationEvent(void); // Record frame events (to internal events array)
|
static void RecordAutomationEvent(void); // Record frame events (to internal events array)
|
||||||
|
|
@ -525,7 +530,7 @@ const char *TextFormat(const char *text, ...); // Formatting of text with variab
|
||||||
#define PLATFORM_DESKTOP_GLFW
|
#define PLATFORM_DESKTOP_GLFW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We're using '#pragma message' because '#warning' is not adopted by MSVC
|
// Using '#pragma message' because '#warning' is not adopted by MSVC
|
||||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||||
#if !defined(SUPPORT_MODULE_RTEXTURES)
|
#if !defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
#pragma message ("WARNING: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly")
|
#pragma message ("WARNING: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly")
|
||||||
|
|
@ -1499,7 +1504,7 @@ Matrix GetCameraMatrix2D(Camera2D camera)
|
||||||
// When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller),
|
// When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller),
|
||||||
// not for the camera getting bigger, hence the invert. Same deal with rotation
|
// not for the camera getting bigger, hence the invert. Same deal with rotation
|
||||||
// 3. Move it by (-offset);
|
// 3. Move it by (-offset);
|
||||||
// Offset defines target transform relative to screen, but since we're effectively "moving" screen (camera)
|
// Offset defines target transform relative to screen, but since effectively "moving" screen (camera)
|
||||||
// we need to do it into opposite direction (inverse transform)
|
// we need to do it into opposite direction (inverse transform)
|
||||||
|
|
||||||
// Having camera transform in world-space, inverse of it gives the modelview transform
|
// Having camera transform in world-space, inverse of it gives the modelview transform
|
||||||
|
|
@ -2753,53 +2758,36 @@ const char *GetApplicationDirectory(void)
|
||||||
// No recursive scanning is done!
|
// No recursive scanning is done!
|
||||||
FilePathList LoadDirectoryFiles(const char *dirPath)
|
FilePathList LoadDirectoryFiles(const char *dirPath)
|
||||||
{
|
{
|
||||||
FilePathList files = { 0 };
|
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
||||||
unsigned int fileCounter = 0;
|
|
||||||
|
|
||||||
struct dirent *entity;
|
|
||||||
DIR *dir = opendir(dirPath);
|
|
||||||
|
|
||||||
if (dir != NULL) // It's a directory
|
|
||||||
{
|
|
||||||
// SCAN 1: Count files
|
|
||||||
while ((entity = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
// NOTE: We skip '.' (current dir) and '..' (parent dir) filepaths
|
|
||||||
if ((strcmp(entity->d_name, ".") != 0) && (strcmp(entity->d_name, "..") != 0)) fileCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory allocation for dirFileCount
|
|
||||||
files.capacity = fileCounter;
|
|
||||||
files.paths = (char **)RL_CALLOC(files.capacity, sizeof(char *));
|
|
||||||
for (unsigned int i = 0; i < files.capacity; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
// SCAN 2: Read filepaths
|
|
||||||
// NOTE: Directory paths are also registered
|
|
||||||
ScanDirectoryFiles(dirPath, &files, NULL);
|
|
||||||
|
|
||||||
// Security check: read files.count should match fileCounter
|
|
||||||
if (files.count != files.capacity) TRACELOG(LOG_WARNING, "FILEIO: Read files count do not match capacity allocated");
|
|
||||||
}
|
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file...
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load directory filepaths with extension filtering and recursive directory scan
|
// Load directory filepaths with extension filtering and recursive directory scan
|
||||||
// NOTE: On recursive loading we do not pre-scan for file count, we use MAX_FILEPATH_CAPACITY
|
// WARNING: Directory is scanned twice, first time to get files count
|
||||||
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
||||||
{
|
{
|
||||||
FilePathList files = { 0 };
|
FilePathList files = { 0 };
|
||||||
|
|
||||||
files.capacity = MAX_FILEPATH_CAPACITY;
|
if (DirectoryExists(basePath)) // It's a directory
|
||||||
files.paths = (char **)RL_CALLOC(files.capacity, sizeof(char *));
|
{
|
||||||
for (unsigned int i = 0; i < files.capacity; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
// SCAN 1: Count files
|
||||||
|
unsigned int fileCounter = GetDirectoryFileCountEx(basePath, filter, scanSubdirs);
|
||||||
|
|
||||||
|
// Memory allocation for dirFileCount
|
||||||
|
files.paths = (char **)RL_CALLOC(fileCounter, sizeof(char *));
|
||||||
|
for (unsigned int i = 0; i < fileCounter; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||||
|
|
||||||
|
// SCAN 2: Read filepaths
|
||||||
// WARNING: basePath is always prepended to scanned paths
|
// WARNING: basePath is always prepended to scanned paths
|
||||||
if (scanSubdirs) ScanDirectoryFilesRecursively(basePath, &files, filter);
|
ScanDirectoryFiles(basePath, &files, filter, fileCounter, scanSubdirs);
|
||||||
else ScanDirectoryFiles(basePath, &files, filter);
|
|
||||||
|
// Security check: read files.count should match fileCounter
|
||||||
|
if (files.count != fileCounter)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "FILEIO: Read files count (%u) does not match capacity allocated (%u)", files.count, fileCounter);
|
||||||
|
files.count = fileCounter; // Avoid memory leak when unloading this FilePathList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file...
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
@ -2810,7 +2798,7 @@ void UnloadDirectoryFiles(FilePathList files)
|
||||||
{
|
{
|
||||||
if (files.paths != NULL)
|
if (files.paths != NULL)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
for (unsigned int i = 0; i < files.count; i++) RL_FREE(files.paths[i]);
|
||||||
|
|
||||||
RL_FREE(files.paths);
|
RL_FREE(files.paths);
|
||||||
}
|
}
|
||||||
|
|
@ -2966,6 +2954,59 @@ void UnloadDroppedFiles(FilePathList files)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the file count in a directory
|
||||||
|
unsigned int GetDirectoryFileCount(const char *dirPath)
|
||||||
|
{
|
||||||
|
return GetDirectoryFileCountEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the file count in a directory with extension filtering and recursive directory scan. Use 'FILE_FILTER_TAG_DIR_ONLY' in the filter string to include directories in the result
|
||||||
|
unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs)
|
||||||
|
{
|
||||||
|
unsigned int fileCounter = 0;
|
||||||
|
|
||||||
|
// WARNING: Path can not be static or it will be reused between recursive function calls!
|
||||||
|
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
||||||
|
memset(path, 0, MAX_FILEPATH_LENGTH);
|
||||||
|
|
||||||
|
struct dirent *entity;
|
||||||
|
DIR *dir = opendir(basePath);
|
||||||
|
|
||||||
|
if (dir != NULL) // It's a directory
|
||||||
|
{
|
||||||
|
while ((entity = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// NOTE: We skip '.' (current dir) and '..' (parent dir) filepaths
|
||||||
|
if ((strcmp(entity->d_name, ".") != 0) && (strcmp(entity->d_name, "..") != 0))
|
||||||
|
{
|
||||||
|
// Construct new path from our base path
|
||||||
|
#if defined(_WIN32)
|
||||||
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, entity->d_name);
|
||||||
|
#else
|
||||||
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, entity->d_name);
|
||||||
|
#endif
|
||||||
|
// Don't add to count if path too long
|
||||||
|
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, basePath);
|
||||||
|
}
|
||||||
|
else if (IsPathFile(path))
|
||||||
|
{
|
||||||
|
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) ||
|
||||||
|
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter)) fileCounter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || (strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL))) fileCounter++;
|
||||||
|
if (scanSubdirs) fileCounter += GetDirectoryFileCountEx(path, filter, scanSubdirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file...
|
||||||
|
return fileCounter;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition: Compression and Encoding
|
// Module Functions Definition: Compression and Encoding
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -3790,7 +3831,6 @@ void PlayAutomationEvent(AutomationEvent event)
|
||||||
// Check if a key has been pressed once
|
// Check if a key has been pressed once
|
||||||
bool IsKeyPressed(int key)
|
bool IsKeyPressed(int key)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
|
if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
|
||||||
|
|
@ -3932,8 +3972,10 @@ bool IsGamepadButtonPressed(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
|
||||||
(CORE.Input.Gamepad.previousButtonState[gamepad][button] == 0) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) pressed = true;
|
{
|
||||||
|
if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 0) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) pressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
@ -3943,8 +3985,10 @@ bool IsGamepadButtonDown(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool down = false;
|
bool down = false;
|
||||||
|
|
||||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
|
||||||
(CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) down = true;
|
{
|
||||||
|
if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1) down = true;
|
||||||
|
}
|
||||||
|
|
||||||
return down;
|
return down;
|
||||||
}
|
}
|
||||||
|
|
@ -3954,8 +3998,10 @@ bool IsGamepadButtonReleased(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
|
||||||
(CORE.Input.Gamepad.previousButtonState[gamepad][button] == 1) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) released = true;
|
{
|
||||||
|
if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 1) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) released = true;
|
||||||
|
}
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
@ -3965,13 +4011,16 @@ bool IsGamepadButtonUp(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool up = false;
|
bool up = false;
|
||||||
|
|
||||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
|
||||||
(CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) up = true;
|
{
|
||||||
|
if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0) up = true;
|
||||||
|
}
|
||||||
|
|
||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the last gamepad button pressed
|
// Get the last gamepad button pressed
|
||||||
|
// NOTE: Returns last gamepad button down, down->up change not considered
|
||||||
int GetGamepadButtonPressed(void)
|
int GetGamepadButtonPressed(void)
|
||||||
{
|
{
|
||||||
return CORE.Input.Gamepad.lastButtonPressed;
|
return CORE.Input.Gamepad.lastButtonPressed;
|
||||||
|
|
@ -4011,10 +4060,13 @@ bool IsMouseButtonPressed(int button)
|
||||||
{
|
{
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
|
if ((button >= 0) && (button <= MOUSE_BUTTON_BACK))
|
||||||
|
{
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) pressed = true;
|
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) pressed = true;
|
||||||
|
|
||||||
// Map touches to mouse buttons checking
|
// Map touches to mouse buttons checking
|
||||||
if ((CORE.Input.Touch.currentTouchState[button] == 1) && (CORE.Input.Touch.previousTouchState[button] == 0)) pressed = true;
|
if ((CORE.Input.Touch.currentTouchState[button] == 1) && (CORE.Input.Touch.previousTouchState[button] == 0)) pressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
@ -4024,10 +4076,13 @@ bool IsMouseButtonDown(int button)
|
||||||
{
|
{
|
||||||
bool down = false;
|
bool down = false;
|
||||||
|
|
||||||
|
if ((button >= 0) && (button <= MOUSE_BUTTON_BACK))
|
||||||
|
{
|
||||||
if (CORE.Input.Mouse.currentButtonState[button] == 1) down = true;
|
if (CORE.Input.Mouse.currentButtonState[button] == 1) down = true;
|
||||||
|
|
||||||
// NOTE: Touches are considered like mouse buttons
|
// NOTE: Touches are considered like mouse buttons
|
||||||
if (CORE.Input.Touch.currentTouchState[button] == 1) down = true;
|
if (CORE.Input.Touch.currentTouchState[button] == 1) down = true;
|
||||||
|
}
|
||||||
|
|
||||||
return down;
|
return down;
|
||||||
}
|
}
|
||||||
|
|
@ -4037,10 +4092,13 @@ bool IsMouseButtonReleased(int button)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
|
if ((button >= 0) && (button <= MOUSE_BUTTON_BACK))
|
||||||
|
{
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) released = true;
|
if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) released = true;
|
||||||
|
|
||||||
// Map touches to mouse buttons checking
|
// Map touches to mouse buttons checking
|
||||||
if ((CORE.Input.Touch.currentTouchState[button] == 0) && (CORE.Input.Touch.previousTouchState[button] == 1)) released = true;
|
if ((CORE.Input.Touch.currentTouchState[button] == 0) && (CORE.Input.Touch.previousTouchState[button] == 1)) released = true;
|
||||||
|
}
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
@ -4050,10 +4108,13 @@ bool IsMouseButtonUp(int button)
|
||||||
{
|
{
|
||||||
bool up = false;
|
bool up = false;
|
||||||
|
|
||||||
|
if ((button >= 0) && (button <= MOUSE_BUTTON_BACK))
|
||||||
|
{
|
||||||
if (CORE.Input.Mouse.currentButtonState[button] == 0) up = true;
|
if (CORE.Input.Mouse.currentButtonState[button] == 0) up = true;
|
||||||
|
|
||||||
// NOTE: Touches are considered like mouse buttons
|
// NOTE: Touches are considered like mouse buttons
|
||||||
if (CORE.Input.Touch.currentTouchState[button] == 0) up = true;
|
if (CORE.Input.Touch.currentTouchState[button] == 0) up = true;
|
||||||
|
}
|
||||||
|
|
||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
@ -4062,6 +4123,7 @@ bool IsMouseButtonUp(int button)
|
||||||
int GetMouseX(void)
|
int GetMouseX(void)
|
||||||
{
|
{
|
||||||
int mouseX = (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
int mouseX = (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
|
||||||
|
|
||||||
return mouseX;
|
return mouseX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4069,6 +4131,7 @@ int GetMouseX(void)
|
||||||
int GetMouseY(void)
|
int GetMouseY(void)
|
||||||
{
|
{
|
||||||
int mouseY = (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
int mouseY = (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
|
||||||
|
|
||||||
return mouseY;
|
return mouseY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4229,66 +4292,7 @@ void SetupViewport(int width, int height)
|
||||||
// Scan all files and directories in a base path
|
// Scan all files and directories in a base path
|
||||||
// WARNING: files.paths[] must be previously allocated and
|
// WARNING: files.paths[] must be previously allocated and
|
||||||
// contain enough space to store all required paths
|
// contain enough space to store all required paths
|
||||||
static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter)
|
static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter, unsigned int expectedFileCount, bool scanSubdirs)
|
||||||
{
|
|
||||||
static char path[MAX_FILEPATH_LENGTH] = { 0 };
|
|
||||||
memset(path, 0, MAX_FILEPATH_LENGTH);
|
|
||||||
|
|
||||||
struct dirent *dp = NULL;
|
|
||||||
DIR *dir = opendir(basePath);
|
|
||||||
|
|
||||||
if (dir != NULL)
|
|
||||||
{
|
|
||||||
while ((dp = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
if ((strcmp(dp->d_name, ".") != 0) &&
|
|
||||||
(strcmp(dp->d_name, "..") != 0))
|
|
||||||
{
|
|
||||||
// Construct new path from our base path
|
|
||||||
#if defined(_WIN32)
|
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name);
|
|
||||||
#else
|
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, basePath);
|
|
||||||
}
|
|
||||||
else if (filter != NULL)
|
|
||||||
{
|
|
||||||
if (IsPathFile(path))
|
|
||||||
{
|
|
||||||
if (IsFileExtension(path, filter))
|
|
||||||
{
|
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
|
||||||
files->count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (strstr(filter, DIRECTORY_FILTER_TAG) != NULL)
|
|
||||||
{
|
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
|
||||||
files->count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
|
||||||
files->count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan all files and directories recursively from a base path
|
|
||||||
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
|
|
||||||
{
|
{
|
||||||
// WARNING: Path can not be static or it will be reused between recursive function calls!
|
// WARNING: Path can not be static or it will be reused between recursive function calls!
|
||||||
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
||||||
|
|
@ -4299,7 +4303,7 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
|
||||||
|
|
||||||
if (dir != NULL)
|
if (dir != NULL)
|
||||||
{
|
{
|
||||||
while (((dp = readdir(dir)) != NULL) && (files->count < files->capacity))
|
while (((dp = readdir(dir)) != NULL) && (files->count < expectedFileCount))
|
||||||
{
|
{
|
||||||
if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0))
|
if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0))
|
||||||
{
|
{
|
||||||
|
|
@ -4316,9 +4320,8 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
|
||||||
}
|
}
|
||||||
else if (IsPathFile(path))
|
else if (IsPathFile(path))
|
||||||
{
|
{
|
||||||
if (filter != NULL)
|
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) ||
|
||||||
{
|
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter))
|
||||||
if (IsFileExtension(path, filter))
|
|
||||||
{
|
{
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
||||||
files->count++;
|
files->count++;
|
||||||
|
|
@ -4326,38 +4329,20 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL)))
|
||||||
files->count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (files->count >= files->capacity)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((filter != NULL) && (strstr(filter, DIRECTORY_FILTER_TAG) != NULL))
|
|
||||||
{
|
{
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
||||||
files->count++;
|
files->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files->count >= files->capacity)
|
if (scanSubdirs) ScanDirectoryFiles(path, files, filter, expectedFileCount, scanSubdirs);
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScanDirectoryFilesRecursively(path, files, filter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath);
|
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath); // Maybe it's a file...
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_AUTOMATION_EVENTS)
|
#if defined(SUPPORT_AUTOMATION_EVENTS)
|
||||||
|
|
|
||||||
55
src/rlgl.h
55
src/rlgl.h
|
|
@ -113,11 +113,11 @@
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
// NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden
|
// NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden
|
||||||
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
|
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllexport) // Building the library as a Win32 shared library (.dll)
|
||||||
#elif defined(BUILD_LIBTYPE_SHARED)
|
#elif defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RLAPI __attribute__((visibility("default"))) // We are building the library as a Unix shared library (.so/.dylib)
|
#define RLAPI __attribute__((visibility("default"))) // Building the library as a Unix shared library (.so/.dylib)
|
||||||
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
|
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllimport) // Using the library as a Win32 shared library (.dll)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Function specifiers definition
|
// Function specifiers definition
|
||||||
|
|
@ -1270,12 +1270,12 @@ void rlLoadIdentity(void)
|
||||||
// Multiply the current matrix by a translation matrix
|
// Multiply the current matrix by a translation matrix
|
||||||
void rlTranslatef(float x, float y, float z)
|
void rlTranslatef(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix matTranslation = {
|
Matrix matTranslation = rlMatrixIdentity();
|
||||||
1.0f, 0.0f, 0.0f, x,
|
|
||||||
0.0f, 1.0f, 0.0f, y,
|
// Set translation component of matrix
|
||||||
0.0f, 0.0f, 1.0f, z,
|
matTranslation.m12 = x;
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
matTranslation.m13 = y;
|
||||||
};
|
matTranslation.m14 = z;
|
||||||
|
|
||||||
// NOTE: We transpose matrix with multiplication order
|
// NOTE: We transpose matrix with multiplication order
|
||||||
*RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
|
*RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
|
||||||
|
|
@ -1329,12 +1329,12 @@ void rlRotatef(float angle, float x, float y, float z)
|
||||||
// Multiply the current matrix by a scaling matrix
|
// Multiply the current matrix by a scaling matrix
|
||||||
void rlScalef(float x, float y, float z)
|
void rlScalef(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix matScale = {
|
Matrix matScale = rlMatrixIdentity();
|
||||||
x, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, y, 0.0f, 0.0f,
|
// Set scale component of matrix
|
||||||
0.0f, 0.0f, z, 0.0f,
|
matScale.m0 = x;
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
matScale.m5 = y;
|
||||||
};
|
matScale.m10 = z;
|
||||||
|
|
||||||
// NOTE: We transpose matrix with multiplication order
|
// NOTE: We transpose matrix with multiplication order
|
||||||
*RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix);
|
*RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix);
|
||||||
|
|
@ -1344,6 +1344,7 @@ void rlScalef(float x, float y, float z)
|
||||||
void rlMultMatrixf(const float *matf)
|
void rlMultMatrixf(const float *matf)
|
||||||
{
|
{
|
||||||
// Matrix creation from array
|
// Matrix creation from array
|
||||||
|
// Conversion from column-major to row-major memory order
|
||||||
Matrix mat = { matf[0], matf[4], matf[8], matf[12],
|
Matrix mat = { matf[0], matf[4], matf[8], matf[12],
|
||||||
matf[1], matf[5], matf[9], matf[13],
|
matf[1], matf[5], matf[9], matf[13],
|
||||||
matf[2], matf[6], matf[10], matf[14],
|
matf[2], matf[6], matf[10], matf[14],
|
||||||
|
|
@ -3731,7 +3732,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
||||||
// Two possible Options:
|
// Two possible Options:
|
||||||
// 1 - Bind texture to color fbo attachment and glReadPixels()
|
// 1 - Bind texture to color fbo attachment and glReadPixels()
|
||||||
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
|
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
|
||||||
// We are using Option 1, just need to care for texture format on retrieval
|
// Using Option 1, just need to care for texture format on retrieval
|
||||||
// NOTE: This behaviour could be conditioned by graphic driver...
|
// NOTE: This behaviour could be conditioned by graphic driver...
|
||||||
unsigned int fboId = rlLoadFramebuffer();
|
unsigned int fboId = rlLoadFramebuffer();
|
||||||
|
|
||||||
|
|
@ -4463,13 +4464,7 @@ void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType
|
||||||
void rlSetUniformMatrix(int locIndex, Matrix mat)
|
void rlSetUniformMatrix(int locIndex, Matrix mat)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
float matfloat[16] = {
|
glUniformMatrix4fv(locIndex, 1, false, rlMatrixToFloat(mat));
|
||||||
mat.m0, mat.m1, mat.m2, mat.m3,
|
|
||||||
mat.m4, mat.m5, mat.m6, mat.m7,
|
|
||||||
mat.m8, mat.m9, mat.m10, mat.m11,
|
|
||||||
mat.m12, mat.m13, mat.m14, mat.m15
|
|
||||||
};
|
|
||||||
glUniformMatrix4fv(locIndex, 1, false, matfloat);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5255,17 +5250,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
||||||
// Get identity matrix
|
// Get identity matrix
|
||||||
static Matrix rlMatrixIdentity(void)
|
static Matrix rlMatrixIdentity(void)
|
||||||
{
|
{
|
||||||
Matrix result = {
|
Matrix matIdentity = { 0 };
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
matIdentity.m0 = 1.0f;
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
matIdentity.m5 = 1.0f;
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
matIdentity.m10 = 1.0f;
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
matIdentity.m15 = 1.0f;
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
return matIdentity;
|
||||||
}
|
}
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// Get float array of matrix data
|
// Get float array of matrix data
|
||||||
|
// Explicit conversion to column-major memory layout
|
||||||
static rl_float16 rlMatrixToFloatV(Matrix mat)
|
static rl_float16 rlMatrixToFloatV(Matrix mat)
|
||||||
{
|
{
|
||||||
rl_float16 result = { 0 };
|
rl_float16 result = { 0 };
|
||||||
|
|
|
||||||
|
|
@ -1754,7 +1754,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
|
||||||
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()
|
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()
|
||||||
// It isn't clear which would be reliably faster in all cases and on all platforms,
|
// It isn't clear which would be reliably faster in all cases and on all platforms,
|
||||||
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
|
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
|
||||||
// no faster, since we're transferring all the transform matrices anyway
|
// no faster, since all the transform matrices are transferred anyway
|
||||||
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
|
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
|
||||||
|
|
||||||
// Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
|
// Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
|
||||||
|
|
@ -4084,7 +4084,7 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)
|
||||||
{
|
{
|
||||||
RayCollision collision = { 0 };
|
RayCollision collision = { 0 };
|
||||||
|
|
||||||
// Note: If ray.position is inside the box, the distance is negative (as if the ray was reversed)
|
// NOTE: If ray.position is inside the box, the distance is negative (as if the ray was reversed)
|
||||||
// Reversing ray.direction will give use the correct result
|
// Reversing ray.direction will give use the correct result
|
||||||
bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&
|
bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&
|
||||||
(ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&
|
(ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,9 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Error rate to calculate how many segments we need to draw a smooth circle,
|
|
||||||
// taken from https://stackoverflow.com/a/2244088
|
|
||||||
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
||||||
|
// Define error rate to calculate how many segments are needed to draw a smooth circle
|
||||||
|
// REF: https://stackoverflow.com/a/2244088
|
||||||
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
||||||
#endif
|
#endif
|
||||||
#ifndef SPLINE_SEGMENT_DIVISIONS
|
#ifndef SPLINE_SEGMENT_DIVISIONS
|
||||||
|
|
@ -318,7 +318,7 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// NOTE: On OpenGL 3.3 and ES2 using QUADS to avoid drawing order issues
|
||||||
void DrawCircleV(Vector2 center, float radius, Color color)
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
{
|
{
|
||||||
DrawCircleSector(center, radius, 0, 360, 36, color);
|
DrawCircleSector(center, radius, 0, 360, 36, color);
|
||||||
|
|
@ -379,7 +379,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
angle += (stepLength*2.0f);
|
angle += (stepLength*2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
// NOTE: In case number of segments is odd, adding one last piece to the cake
|
||||||
if ((((unsigned int)segments)%2) == 1)
|
if ((((unsigned int)segments)%2) == 1)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
@ -722,7 +722,7 @@ void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// NOTE: On OpenGL 3.3 and ES2 using QUADS to avoid drawing order issues
|
||||||
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||||
{
|
{
|
||||||
DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
|
DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
|
||||||
|
|
@ -968,7 +968,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Quick sketch to make sense of all of this,
|
Quick sketch to make sense of all of this,
|
||||||
there are 9 parts to draw, also mark the 12 points we'll use
|
there are 9 parts to draw, also mark the 12 points used
|
||||||
|
|
||||||
P0____________________P1
|
P0____________________P1
|
||||||
/| |\
|
/| |\
|
||||||
|
|
@ -1024,7 +1024,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
// NOTE: In case number of segments is odd, adding one last piece to the cake
|
||||||
if (segments%2)
|
if (segments%2)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
@ -1168,7 +1168,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
// Draw rectangle with rounded edges
|
// Draw rectangle with rounded edges
|
||||||
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
|
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
|
||||||
{
|
{
|
||||||
// NOTE: For line thicknes <=1.0f we use RL_LINES, otherwise wee use RL_QUADS/RL_TRIANGLES
|
// NOTE: For line thicknes <=1.0f using RL_LINES, otherwise using RL_QUADS/RL_TRIANGLES
|
||||||
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
|
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1204,7 +1204,7 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Quick sketch to make sense of all of this,
|
Quick sketch to make sense of all of this,
|
||||||
marks the 16 + 4(corner centers P16-19) points we'll use
|
marks the 16 + 4(corner centers P16-19) points used
|
||||||
|
|
||||||
P0 ================== P1
|
P0 ================== P1
|
||||||
// P8 P9 \\
|
// P8 P9 \\
|
||||||
|
|
@ -1946,7 +1946,7 @@ void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, C
|
||||||
// Draw spline segment: Linear, 2 points
|
// Draw spline segment: Linear, 2 points
|
||||||
void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color)
|
void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color)
|
||||||
{
|
{
|
||||||
// NOTE: For the linear spline we don't use subdivisions, just a single quad
|
// NOTE: For the linear spline no subdivisions are used, just a single quad
|
||||||
|
|
||||||
Vector2 delta = { p2.x - p1.x, p2.y - p1.y };
|
Vector2 delta = { p2.x - p1.x, p2.y - p1.y };
|
||||||
float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
|
float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
|
||||||
|
|
|
||||||
20
src/rtext.c
20
src/rtext.c
|
|
@ -1727,7 +1727,6 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
|
|
||||||
// Replace text string
|
// Replace text string
|
||||||
// REQUIRES: strstr(), strncpy()
|
// REQUIRES: strstr(), strncpy()
|
||||||
// TODO: If (replacement == "") remove "search" text
|
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *TextReplace(const char *text, const char *search, const char *replacement)
|
char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
{
|
{
|
||||||
|
|
@ -1735,6 +1734,8 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
|
|
||||||
if ((text != NULL) && (search != NULL))
|
if ((text != NULL) && (search != NULL))
|
||||||
{
|
{
|
||||||
|
if (replacement == NULL) replacement = "";
|
||||||
|
|
||||||
char *insertPoint = NULL; // Next insert point
|
char *insertPoint = NULL; // Next insert point
|
||||||
char *temp = NULL; // Temp pointer
|
char *temp = NULL; // Temp pointer
|
||||||
int textLen = 0; // Text string length
|
int textLen = 0; // Text string length
|
||||||
|
|
@ -1768,15 +1769,14 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
insertPoint = (char *)strstr(text, search);
|
insertPoint = (char *)strstr(text, search);
|
||||||
lastReplacePos = (int)(insertPoint - text);
|
lastReplacePos = (int)(insertPoint - text);
|
||||||
|
|
||||||
// TODO: Review logic to avoid strcpy()
|
memcpy(temp, text, lastReplacePos);
|
||||||
// OK - Those lines work
|
temp += lastReplacePos;
|
||||||
temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
|
|
||||||
temp = strcpy(temp, replacement) + replaceLen;
|
if (replaceLen > 0)
|
||||||
// WRONG - But not those ones
|
{
|
||||||
//temp = strncpy(temp, text, tempLen - 1) + lastReplacePos;
|
memcpy(temp, replacement, replaceLen);
|
||||||
//tempLen -= lastReplacePos;
|
temp += replaceLen;
|
||||||
//temp = strncpy(temp, replacement, tempLen - 1) + replaceLen;
|
}
|
||||||
//tempLen -= replaceLen;
|
|
||||||
|
|
||||||
text += lastReplacePos + searchLen; // Move to next "end of replace"
|
text += lastReplacePos + searchLen; // Move to next "end of replace"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1324,11 +1324,6 @@
|
||||||
"name": "FilePathList",
|
"name": "FilePathList",
|
||||||
"description": "File path list",
|
"description": "File path list",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
|
||||||
"type": "unsigned int",
|
|
||||||
"name": "capacity",
|
|
||||||
"description": "Filepaths max entries"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "unsigned int",
|
"type": "unsigned int",
|
||||||
"name": "count",
|
"name": "count",
|
||||||
|
|
@ -4734,6 +4729,36 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "GetDirectoryFileCount",
|
||||||
|
"description": "Get the file count in a directory",
|
||||||
|
"returnType": "unsigned int",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "dirPath"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GetDirectoryFileCountEx",
|
||||||
|
"description": "Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
||||||
|
"returnType": "unsigned int",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "basePath"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "const char *",
|
||||||
|
"name": "filter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "bool",
|
||||||
|
"name": "scanSubdirs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "CompressData",
|
"name": "CompressData",
|
||||||
"description": "Compress data (DEFLATE algorithm), memory must be MemFree()",
|
"description": "Compress data (DEFLATE algorithm), memory must be MemFree()",
|
||||||
|
|
|
||||||
|
|
@ -1324,11 +1324,6 @@ return {
|
||||||
name = "FilePathList",
|
name = "FilePathList",
|
||||||
description = "File path list",
|
description = "File path list",
|
||||||
fields = {
|
fields = {
|
||||||
{
|
|
||||||
type = "unsigned int",
|
|
||||||
name = "capacity",
|
|
||||||
description = "Filepaths max entries"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type = "unsigned int",
|
type = "unsigned int",
|
||||||
name = "count",
|
name = "count",
|
||||||
|
|
@ -4230,6 +4225,24 @@ return {
|
||||||
{type = "FilePathList", name = "files"}
|
{type = "FilePathList", name = "files"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name = "GetDirectoryFileCount",
|
||||||
|
description = "Get the file count in a directory",
|
||||||
|
returnType = "unsigned int",
|
||||||
|
params = {
|
||||||
|
{type = "const char *", name = "dirPath"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "GetDirectoryFileCountEx",
|
||||||
|
description = "Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
||||||
|
returnType = "unsigned int",
|
||||||
|
params = {
|
||||||
|
{type = "const char *", name = "basePath"},
|
||||||
|
{type = "const char *", name = "filter"},
|
||||||
|
{type = "bool", name = "scanSubdirs"}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name = "CompressData",
|
name = "CompressData",
|
||||||
description = "Compress data (DEFLATE algorithm), memory must be MemFree()",
|
description = "Compress data (DEFLATE algorithm), memory must be MemFree()",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -280,8 +280,7 @@
|
||||||
<Field type="float[2]" name="scale" desc="VR distortion scale" />
|
<Field type="float[2]" name="scale" desc="VR distortion scale" />
|
||||||
<Field type="float[2]" name="scaleIn" desc="VR distortion scale in" />
|
<Field type="float[2]" name="scaleIn" desc="VR distortion scale in" />
|
||||||
</Struct>
|
</Struct>
|
||||||
<Struct name="FilePathList" fieldCount="3" desc="File path list">
|
<Struct name="FilePathList" fieldCount="2" desc="File path list">
|
||||||
<Field type="unsigned int" name="capacity" desc="Filepaths max entries" />
|
|
||||||
<Field type="unsigned int" name="count" desc="Filepaths entries count" />
|
<Field type="unsigned int" name="count" desc="Filepaths entries count" />
|
||||||
<Field type="char **" name="paths" desc="Filepaths entries" />
|
<Field type="char **" name="paths" desc="Filepaths entries" />
|
||||||
</Struct>
|
</Struct>
|
||||||
|
|
@ -679,7 +678,7 @@
|
||||||
<Param type="unsigned int" name="frames" desc="" />
|
<Param type="unsigned int" name="frames" desc="" />
|
||||||
</Callback>
|
</Callback>
|
||||||
</Callbacks>
|
</Callbacks>
|
||||||
<Functions count="597">
|
<Functions count="599">
|
||||||
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
|
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
|
||||||
<Param type="int" name="width" desc="" />
|
<Param type="int" name="width" desc="" />
|
||||||
<Param type="int" name="height" desc="" />
|
<Param type="int" name="height" desc="" />
|
||||||
|
|
@ -1137,6 +1136,14 @@
|
||||||
<Function name="UnloadDroppedFiles" retType="void" paramCount="1" desc="Unload dropped filepaths">
|
<Function name="UnloadDroppedFiles" retType="void" paramCount="1" desc="Unload dropped filepaths">
|
||||||
<Param type="FilePathList" name="files" desc="" />
|
<Param type="FilePathList" name="files" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
|
<Function name="GetDirectoryFileCount" retType="unsigned int" paramCount="1" desc="Get the file count in a directory">
|
||||||
|
<Param type="const char *" name="dirPath" desc="" />
|
||||||
|
</Function>
|
||||||
|
<Function name="GetDirectoryFileCountEx" retType="unsigned int" paramCount="3" desc="Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
|
||||||
|
<Param type="const char *" name="basePath" desc="" />
|
||||||
|
<Param type="const char *" name="filter" desc="" />
|
||||||
|
<Param type="bool" name="scanSubdirs" desc="" />
|
||||||
|
</Function>
|
||||||
<Function name="CompressData" retType="unsigned char *" paramCount="3" desc="Compress data (DEFLATE algorithm), memory must be MemFree()">
|
<Function name="CompressData" retType="unsigned char *" paramCount="3" desc="Compress data (DEFLATE algorithm), memory must be MemFree()">
|
||||||
<Param type="const unsigned char *" name="data" desc="" />
|
<Param type="const unsigned char *" name="data" desc="" />
|
||||||
<Param type="int" name="dataSize" desc="" />
|
<Param type="int" name="dataSize" desc="" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user