Merge branch 'raysan5-master'
This commit is contained in:
commit
da6b05e15c
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"cmake.configureOnOpen": true
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,10 @@
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
// NOTE: Storage positions must start with 0, directly related to file memory layout
|
// NOTE: Storage positions must start with 0, directly related to file memory layout
|
||||||
typedef enum { STORAGE_SCORE = 0, STORAGE_HISCORE } StorageData;
|
typedef enum {
|
||||||
|
STORAGE_POSITION_SCORE = 0,
|
||||||
|
STORAGE_POSITION_HISCORE = 1
|
||||||
|
} StorageData;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|
@ -43,14 +46,14 @@ int main(void)
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_ENTER))
|
if (IsKeyPressed(KEY_ENTER))
|
||||||
{
|
{
|
||||||
StorageSaveValue(STORAGE_SCORE, score);
|
SaveStorageValue(STORAGE_POSITION_SCORE, score);
|
||||||
StorageSaveValue(STORAGE_HISCORE, hiscore);
|
SaveStorageValue(STORAGE_POSITION_HISCORE, hiscore);
|
||||||
}
|
}
|
||||||
else if (IsKeyPressed(KEY_SPACE))
|
else if (IsKeyPressed(KEY_SPACE))
|
||||||
{
|
{
|
||||||
// NOTE: If requested position could not be found, value 0 is returned
|
// NOTE: If requested position could not be found, value 0 is returned
|
||||||
score = StorageLoadValue(STORAGE_SCORE);
|
score = LoadStorageValue(STORAGE_POSITION_SCORE);
|
||||||
hiscore = StorageLoadValue(STORAGE_HISCORE);
|
hiscore = LoadStorageValue(STORAGE_POSITION_HISCORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
framesCounter++;
|
framesCounter++;
|
||||||
|
|
|
||||||
105
examples/models/models_animation_gltf.c
Normal file
105
examples/models/models_animation_gltf.c
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [models] example - Load 3d model with animations and play them
|
||||||
|
*
|
||||||
|
* This example has been created using raylib 3.0 (www.raylib.com)
|
||||||
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
|
*
|
||||||
|
* Example contributed by Tyler Bezera (@gamerfiend) and reviewed by Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Tyler Bezera (@gamerfiend) and Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "raylib.h"
|
||||||
|
#define RGLTFANIMATION_IMPLEMENTATION
|
||||||
|
#include "rgltfanim.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [models] example - model animation gltf");
|
||||||
|
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
Camera camera = { 0 };
|
||||||
|
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
|
||||||
|
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||||
|
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||||
|
camera.fovy = 45.0f; // Camera field-of-view Y
|
||||||
|
camera.type = CAMERA_PERSPECTIVE; // Camera mode type
|
||||||
|
|
||||||
|
// Load the animated model mesh and basic data
|
||||||
|
Model model = LoadModel("resources/models/RiggedFigure.glb");
|
||||||
|
|
||||||
|
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
|
||||||
|
|
||||||
|
// Load animation data
|
||||||
|
// int animsCount = 0;
|
||||||
|
ModelAnimationsGLTF anims = LoadModelGLTFAnimations("resources/models/RiggedFigure.glb");
|
||||||
|
// int animFrameCounter = 0;
|
||||||
|
|
||||||
|
SetCameraMode(camera, CAMERA_FREE); // Set free camera mode
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
UpdateCamera(&camera);
|
||||||
|
|
||||||
|
// Play animation when spacebar is held down
|
||||||
|
if (IsKeyDown(KEY_SPACE))
|
||||||
|
{
|
||||||
|
// animFrameCounter++;
|
||||||
|
UpdateModelAnimationGLTF(model, 0, 0.5);
|
||||||
|
// if (animFrameCounter >= anims[0].frameCount) animFrameCounter = 0;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
BeginMode3D(camera);
|
||||||
|
|
||||||
|
DrawModelEx(model, position, (Vector3){ 1.0f, 0.0f, 0.0f }, -90.0f, (Vector3){ 1.0f, 1.0f, 1.0f }, WHITE);
|
||||||
|
|
||||||
|
for (int i = 0; i < model.boneCount; i++)
|
||||||
|
{
|
||||||
|
//DrawCube(anims[0].framePoses[animFrameCounter][i].translation, 0.2f, 0.2f, 0.2f, RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawGrid(10, 1.0f); // Draw a grid
|
||||||
|
|
||||||
|
EndMode3D();
|
||||||
|
|
||||||
|
DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, 10, 20, MAROON);
|
||||||
|
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload model animations data
|
||||||
|
// for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]);
|
||||||
|
// RL_FREE(anims);
|
||||||
|
|
||||||
|
UnloadModel(model); // Unload model
|
||||||
|
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
examples/models/resources/models/RiggedFigure.glb
Normal file
BIN
examples/models/resources/models/RiggedFigure.glb
Normal file
Binary file not shown.
257
examples/models/rgltfanim.h
Normal file
257
examples/models/rgltfanim.h
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.gltfanimation - Simple module to have animation support with GLTF models, based on the
|
||||||
|
* implementation work for Google's Filament engine.
|
||||||
|
*
|
||||||
|
* CONFIGURATION:
|
||||||
|
*
|
||||||
|
* #define RGLTFANIMATION_IMPLEMENTATION
|
||||||
|
* Generates the implementation of the library into the included file.
|
||||||
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
|
*
|
||||||
|
* LICENSE: zlib/libpng
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Tyler Bezera and Ramon Santamaria
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RGLTFANIM_H
|
||||||
|
#define RGLTFANIM_H
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "../../src/external/cgltf.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TYPE_LINEAR,
|
||||||
|
TYPE_STEP,
|
||||||
|
TYPE_CUBICSPLINE
|
||||||
|
} AnimationGLTFInterpolationType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TYPE_TRANSLATION,
|
||||||
|
TYPE_ROTATION,
|
||||||
|
TYPE_SCALE,
|
||||||
|
TYPE_WEIGHTS
|
||||||
|
} AnimationGLTFPathType;
|
||||||
|
|
||||||
|
typedef struct ModelGLTFAnimationSampler
|
||||||
|
{
|
||||||
|
AnimationGLTFInterpolationType interpolationType;
|
||||||
|
float *sourceValues;
|
||||||
|
int sourceValuesCount;
|
||||||
|
} ModelGLTFAnimationSampler;
|
||||||
|
|
||||||
|
typedef struct ModelGLTFAnimationChannel
|
||||||
|
{
|
||||||
|
AnimationGLTFPathType pathType;
|
||||||
|
ModelGLTFAnimationSampler *sourceData;
|
||||||
|
Model targetModel;
|
||||||
|
} ModelGLTFAnimationChannel;
|
||||||
|
|
||||||
|
typedef struct ModelAnimationGLTF
|
||||||
|
{
|
||||||
|
char animationName[50];
|
||||||
|
|
||||||
|
ModelGLTFAnimationSampler *samplers;
|
||||||
|
int samplersCount;
|
||||||
|
|
||||||
|
ModelGLTFAnimationChannel *channels;
|
||||||
|
int channelsCount;
|
||||||
|
|
||||||
|
float duration;
|
||||||
|
float start;
|
||||||
|
float end;
|
||||||
|
} ModelAnimationGLTF;
|
||||||
|
|
||||||
|
typedef struct ModelAnimationsGLTF
|
||||||
|
{
|
||||||
|
ModelAnimationGLTF *animations;
|
||||||
|
int animationsCount;
|
||||||
|
|
||||||
|
Matrix *boneMatrices;
|
||||||
|
int boneMatricesCount;
|
||||||
|
} ModelAnimationsGLTF;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{ // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
ModelAnimationsGLTF LoadModelGLTFAnimations(const char *filename);
|
||||||
|
void UpdateModelAnimationGLTF(Model model, int animationIndex, float time);
|
||||||
|
void createSampler(cgltf_animation_sampler *src, ModelGLTFAnimationSampler *dst);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //RGLTFANIM_H
|
||||||
|
|
||||||
|
/***********************************************************************************
|
||||||
|
*
|
||||||
|
* RGLTFANIM IMPLEMENTATION
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(RGLTFANIMATION_IMPLEMENTATION)
|
||||||
|
#include "raylib.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
//#define CGLTF_IMPLEMENTATION
|
||||||
|
#include "../../src/external/cgltf.h"
|
||||||
|
|
||||||
|
void createSampler(cgltf_animation_sampler *src, ModelGLTFAnimationSampler *dst) {
|
||||||
|
//uint8_t *tileLineBlob = (uint8_t*)src->input->buffer_view->buffer->data;
|
||||||
|
//float *tileLineFloats = (float*)(tileLineBlob + src->input->offset + src->input->buffer_view->offset);
|
||||||
|
|
||||||
|
for (int i = 0, len = src->input->count; i < len; ++i) {
|
||||||
|
|
||||||
|
//TODO: Need to support map
|
||||||
|
//dst->times
|
||||||
|
|
||||||
|
switch (src->output->type) {
|
||||||
|
case cgltf_type_scalar:
|
||||||
|
dst->sourceValues = RL_CALLOC(src->output->count, sizeof(float));
|
||||||
|
cgltf_accessor_unpack_floats(src->output, &dst->sourceValues[0], src->output->count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_type_vec3:
|
||||||
|
dst->sourceValues = RL_CALLOC(src->output->count * 3, sizeof(float));
|
||||||
|
cgltf_accessor_unpack_floats(src->output, &dst->sourceValues[0], src->output->count * 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_type_vec4:
|
||||||
|
dst->sourceValues = RL_CALLOC(src->output->count * 3, sizeof(float));
|
||||||
|
cgltf_accessor_unpack_floats(src->output, &dst->sourceValues[0], src->output->count * 3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (src->interpolation) {
|
||||||
|
case cgltf_interpolation_type_linear:
|
||||||
|
dst->interpolationType = TYPE_LINEAR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_interpolation_type_step:
|
||||||
|
dst->interpolationType = TYPE_STEP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_interpolation_type_cubic_spline:
|
||||||
|
dst->interpolationType = TYPE_CUBICSPLINE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTransformType(cgltf_animation_channel *src, ModelGLTFAnimationChannel *dst) {
|
||||||
|
switch (src->target_path) {
|
||||||
|
case cgltf_animation_path_type_translation:
|
||||||
|
dst->pathType = TYPE_TRANSLATION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_animation_path_type_rotation:
|
||||||
|
dst->pathType = TYPE_ROTATION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_animation_path_type_scale:
|
||||||
|
dst->pathType = TYPE_SCALE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_animation_path_type_weights:
|
||||||
|
dst->pathType = TYPE_WEIGHTS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelAnimationsGLTF LoadModelGLTFAnimations(const char *fileName) {
|
||||||
|
|
||||||
|
ModelAnimationsGLTF animationsGLTF = { 0 };
|
||||||
|
// glTF file loading
|
||||||
|
FILE *gltfFile = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (gltfFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "[%s] glTF file could not be opened", fileName);
|
||||||
|
return animationsGLTF;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(gltfFile, 0, SEEK_END);
|
||||||
|
int size = ftell(gltfFile);
|
||||||
|
fseek(gltfFile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
void *buffer = RL_MALLOC(size);
|
||||||
|
fread(buffer, size, 1, gltfFile);
|
||||||
|
|
||||||
|
fclose(gltfFile);
|
||||||
|
|
||||||
|
// glTF data loading
|
||||||
|
cgltf_options options = { 0 };
|
||||||
|
cgltf_data *data = NULL;
|
||||||
|
cgltf_result result = cgltf_parse(&options, buffer, size, &data);
|
||||||
|
|
||||||
|
if (result == cgltf_result_success)
|
||||||
|
{
|
||||||
|
// Read data buffers
|
||||||
|
result = cgltf_load_buffers(&options, data, fileName);
|
||||||
|
if (result != cgltf_result_success) TraceLog(LOG_INFO, "[%s][%s] Error loading mesh/material buffers", fileName, (data->file_type == 2)? "glb" : "gltf");
|
||||||
|
|
||||||
|
//Animation count
|
||||||
|
int animationsCount = data->animations_count;
|
||||||
|
|
||||||
|
//Initialize our animations array
|
||||||
|
animationsGLTF.animationsCount = animationsCount;
|
||||||
|
animationsGLTF.animations = RL_CALLOC(animationsCount, sizeof(ModelAnimationGLTF));
|
||||||
|
|
||||||
|
//Loop through each Animation
|
||||||
|
for (int i = 0; i < animationsCount; i++) {
|
||||||
|
//Copy Animation name
|
||||||
|
if(data->animations[i].name) TextCopy(animationsGLTF.animations[i].animationName, data->animations[i].name);
|
||||||
|
|
||||||
|
int samplerCount = data->animations[i].samplers_count;
|
||||||
|
animationsGLTF.animations[i].samplersCount = samplerCount;
|
||||||
|
animationsGLTF.animations[i].samplers = RL_CALLOC(samplerCount, sizeof(ModelGLTFAnimationSampler));
|
||||||
|
for (int j = 0; j < samplerCount; j++) {
|
||||||
|
createSampler(&data->animations[i].samplers[j], &animationsGLTF.animations[i].samplers[j]);
|
||||||
|
//TODO handle map times
|
||||||
|
}
|
||||||
|
|
||||||
|
int channelCount = data->animations[i].channels_count;
|
||||||
|
animationsGLTF.animations[i].channelsCount = channelCount;
|
||||||
|
animationsGLTF.animations[i].channels = RL_CALLOC(channelCount, sizeof(ModelGLTFAnimationChannel));
|
||||||
|
for (int j = 0; j < channelCount; j++) {
|
||||||
|
//TODO Model stuff? Also... strange pointer arthmetic? data->animations[i].channels[j].sampler - data->animations[i].samplers??
|
||||||
|
animationsGLTF.animations[i].channels[j].sourceData = &animationsGLTF.animations[i].samplers[data->animations[i].channels[j].sampler - data->animations[i].samplers];
|
||||||
|
setTransformType(&data->animations[i].channels[j], &animationsGLTF.animations[i].channels[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return animationsGLTF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateModelAnimationGLTF(Model model, int animationIndex, float time) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -54,6 +54,8 @@
|
||||||
|
|
||||||
#include <GLFW/glfw3.h> // Windows/Context and inputs management
|
#include <GLFW/glfw3.h> // Windows/Context and inputs management
|
||||||
|
|
||||||
|
#include <stdio.h> // Required for: printf()
|
||||||
|
|
||||||
#define RED (Color){ 230, 41, 55, 255 } // Red
|
#define RED (Color){ 230, 41, 55, 255 } // Red
|
||||||
#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo)
|
#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo)
|
||||||
#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray
|
#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray
|
||||||
|
|
@ -86,10 +88,10 @@ int main(void)
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
{
|
{
|
||||||
TraceLog(LOG_WARNING, "GLFW3: Can not initialize GLFW");
|
printf("GLFW3: Can not initialize GLFW\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else TraceLog(LOG_INFO, "GLFW3: GLFW initialized successfully");
|
else printf("GLFW3: GLFW initialized successfully\n");
|
||||||
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||||
|
|
@ -105,7 +107,7 @@ int main(void)
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else TraceLog(LOG_INFO, "GLFW3: Window created successfully");
|
else printf("GLFW3: Window created successfully\n");
|
||||||
|
|
||||||
glfwSetWindowPos(window, 200, 200);
|
glfwSetWindowPos(window, 200, 200);
|
||||||
|
|
||||||
|
|
@ -217,7 +219,7 @@ int main(void)
|
||||||
// GLFW3: Error callback
|
// GLFW3: Error callback
|
||||||
static void ErrorCallback(int error, const char *description)
|
static void ErrorCallback(int error, const char *description)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, description);
|
fprintf(stderr, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3: Keyboard callback
|
// GLFW3: Keyboard callback
|
||||||
|
|
|
||||||
19
src/Makefile
19
src/Makefile
|
|
@ -150,7 +150,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
EMSDK_PATH ?= C:/emsdk
|
EMSDK_PATH ?= C:/emsdk
|
||||||
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
|
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
|
||||||
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
|
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
|
||||||
PYTHON_PATH = $(EMSDK_PATH)/python/2.7.13.1_64bit/python-2.7.13.amd64
|
PYTHON_PATH = $(EMSDK_PATH)/python/3.7.4_64bit
|
||||||
NODE_PATH = $(EMSDK_PATH)/node/12.9.1_64bit/bin
|
NODE_PATH = $(EMSDK_PATH)/node/12.9.1_64bit/bin
|
||||||
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
|
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
|
||||||
endif
|
endif
|
||||||
|
|
@ -291,9 +291,16 @@ endif
|
||||||
|
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
|
CFLAGS += -s ASSERTIONS=1 --profiling
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
|
ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
|
||||||
CFLAGS += -O1
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
|
CFLAGS += -Os
|
||||||
|
else
|
||||||
|
CFLAGS += -s -O1
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Additional flags for compiler (if desired)
|
# Additional flags for compiler (if desired)
|
||||||
|
|
@ -311,18 +318,12 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
# -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
|
# -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
|
||||||
# -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
|
# -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
|
||||||
# -s USE_PTHREADS=1 # multithreading support
|
# -s USE_PTHREADS=1 # multithreading support
|
||||||
# -s WASM=0 # disable Web Assembly, emitted by default
|
|
||||||
# -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow)
|
|
||||||
# -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter
|
|
||||||
# -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data
|
# -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data
|
||||||
# -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
|
# -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
|
||||||
# --profiling # include information for code profiling
|
# --profiling # include information for code profiling
|
||||||
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
||||||
# --preload-file resources # specify a resources folder for data compilation
|
# --preload-file resources # specify a resources folder for data compilation
|
||||||
CFLAGS += -s USE_GLFW=3
|
CFLAGS += -s USE_GLFW=3
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
|
||||||
CFLAGS += -s ASSERTIONS=1 --profiling
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
# Compiler flags for arquitecture
|
# Compiler flags for arquitecture
|
||||||
|
|
@ -477,7 +478,7 @@ endif
|
||||||
raylib: $(OBJS)
|
raylib: $(OBJS)
|
||||||
ifeq ($(PLATFORM),PLATFORM_WEB)
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
# Compile raylib for web.
|
# Compile raylib for web.
|
||||||
emcc -O1 $(OBJS) -o $(RAYLIB_RELEASE_PATH)/libraylib.bc
|
$(CC) -O1 $(OBJS) -o $(RAYLIB_RELEASE_PATH)/libraylib.bc
|
||||||
@echo "raylib library generated (libraylib.bc)!"
|
@echo "raylib library generated (libraylib.bc)!"
|
||||||
else
|
else
|
||||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||||
|
|
|
||||||
17
src/config.h
17
src/config.h
|
|
@ -53,13 +53,15 @@
|
||||||
// Wait for events passively (sleeping while no events) instead of polling them actively every frame
|
// Wait for events passively (sleeping while no events) instead of polling them actively every frame
|
||||||
//#define SUPPORT_EVENTS_WAITING 1
|
//#define SUPPORT_EVENTS_WAITING 1
|
||||||
// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
||||||
#define SUPPORT_SCREEN_CAPTURE 1
|
//#define SUPPORT_SCREEN_CAPTURE 1
|
||||||
// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
|
// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
|
||||||
#define SUPPORT_GIF_RECORDING 1
|
//#define SUPPORT_GIF_RECORDING 1
|
||||||
// Allow scale all the drawn content to match the high-DPI equivalent size (only PLATFORM_DESKTOP)
|
// Allow scale all the drawn content to match the high-DPI equivalent size (only PLATFORM_DESKTOP)
|
||||||
//#define SUPPORT_HIGH_DPI 1
|
//#define SUPPORT_HIGH_DPI 1
|
||||||
// Support CompressData() and DecompressData() functions
|
// Support CompressData() and DecompressData() functions
|
||||||
#define SUPPORT_COMPRESSION_API 1
|
#define SUPPORT_COMPRESSION_API 1
|
||||||
|
// Support saving binary data automatically to a generated storage.data file. This file is managed internally.
|
||||||
|
#define SUPPORT_DATA_STORAGE 1
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: rlgl - Configuration Flags
|
// Module: rlgl - Configuration Flags
|
||||||
|
|
@ -87,12 +89,13 @@
|
||||||
//#define SUPPORT_FILEFORMAT_JPG 1
|
//#define SUPPORT_FILEFORMAT_JPG 1
|
||||||
#define SUPPORT_FILEFORMAT_GIF 1
|
#define SUPPORT_FILEFORMAT_GIF 1
|
||||||
//#define SUPPORT_FILEFORMAT_PSD 1
|
//#define SUPPORT_FILEFORMAT_PSD 1
|
||||||
#define SUPPORT_FILEFORMAT_DDS 1
|
//#define SUPPORT_FILEFORMAT_DDS 1
|
||||||
#define SUPPORT_FILEFORMAT_HDR 1
|
//#define SUPPORT_FILEFORMAT_HDR 1
|
||||||
//#define SUPPORT_FILEFORMAT_KTX 1
|
//#define SUPPORT_FILEFORMAT_KTX 1
|
||||||
//#define SUPPORT_FILEFORMAT_ASTC 1
|
//#define SUPPORT_FILEFORMAT_ASTC 1
|
||||||
//#define SUPPORT_FILEFORMAT_PKM 1
|
//#define SUPPORT_FILEFORMAT_PKM 1
|
||||||
//#define SUPPORT_FILEFORMAT_PVR 1
|
//#define SUPPORT_FILEFORMAT_PVR 1
|
||||||
|
|
||||||
// Support image export functionality (.png, .bmp, .tga, .jpg)
|
// Support image export functionality (.png, .bmp, .tga, .jpg)
|
||||||
#define SUPPORT_IMAGE_EXPORT 1
|
#define SUPPORT_IMAGE_EXPORT 1
|
||||||
// Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
|
// Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
|
||||||
|
|
@ -117,7 +120,7 @@
|
||||||
// Selected desired model fileformats to be supported for loading
|
// Selected desired model fileformats to be supported for loading
|
||||||
#define SUPPORT_FILEFORMAT_OBJ 1
|
#define SUPPORT_FILEFORMAT_OBJ 1
|
||||||
#define SUPPORT_FILEFORMAT_MTL 1
|
#define SUPPORT_FILEFORMAT_MTL 1
|
||||||
#define SUPPORT_FILEFORMAT_IQM 1
|
//#define SUPPORT_FILEFORMAT_IQM 1
|
||||||
#define SUPPORT_FILEFORMAT_GLTF 1
|
#define SUPPORT_FILEFORMAT_GLTF 1
|
||||||
// Support procedural mesh generation functions, uses external par_shapes.h library
|
// Support procedural mesh generation functions, uses external par_shapes.h library
|
||||||
// NOTE: Some generated meshes DO NOT include generated texture coordinates
|
// NOTE: Some generated meshes DO NOT include generated texture coordinates
|
||||||
|
|
@ -131,8 +134,8 @@
|
||||||
#define SUPPORT_FILEFORMAT_OGG 1
|
#define SUPPORT_FILEFORMAT_OGG 1
|
||||||
#define SUPPORT_FILEFORMAT_XM 1
|
#define SUPPORT_FILEFORMAT_XM 1
|
||||||
#define SUPPORT_FILEFORMAT_MOD 1
|
#define SUPPORT_FILEFORMAT_MOD 1
|
||||||
#define SUPPORT_FILEFORMAT_FLAC 1
|
//#define SUPPORT_FILEFORMAT_FLAC 1
|
||||||
#define SUPPORT_FILEFORMAT_MP3 1
|
//#define SUPPORT_FILEFORMAT_MP3 1
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: utils - Configuration Flags
|
// Module: utils - Configuration Flags
|
||||||
|
|
|
||||||
233
src/core.c
233
src/core.c
|
|
@ -82,6 +82,9 @@
|
||||||
* provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module
|
* provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module
|
||||||
* for linkage
|
* for linkage
|
||||||
*
|
*
|
||||||
|
* #define SUPPORT_DATA_STORAGE
|
||||||
|
* Support saving binary data automatically to a generated storage.data file. This file is managed internally.
|
||||||
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
|
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
|
||||||
* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
|
* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
|
||||||
|
|
@ -152,7 +155,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: srand(), rand(), atexit()
|
#include <stdlib.h> // Required for: srand(), rand(), atexit()
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fseek(), fread(), fwrite(), fclose() [Used in StorageSaveValue()/StorageLoadValue()]
|
|
||||||
#include <string.h> // Required for: strrchr(), strcmp(), strlen()
|
#include <string.h> // Required for: strrchr(), strcmp(), strlen()
|
||||||
#include <time.h> // Required for: time() [Used in InitTimer()]
|
#include <time.h> // Required for: time() [Used in InitTimer()]
|
||||||
#include <math.h> // Required for: tan() [Used in BeginMode3D()]
|
#include <math.h> // Required for: tan() [Used in BeginMode3D()]
|
||||||
|
|
@ -283,12 +285,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
|
||||||
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
||||||
|
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
||||||
|
|
||||||
#define MAX_CHARS_QUEUE 16 // Max number of characters in the input queue
|
#define MAX_CHARS_QUEUE 16 // Max number of characters in the input queue
|
||||||
|
|
||||||
#define STORAGE_FILENAME "storage.data"
|
#if defined(SUPPORT_DATA_STORAGE)
|
||||||
|
#define STORAGE_DATA_FILE "storage.data"
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
|
|
@ -308,9 +312,9 @@ typedef struct {
|
||||||
} InputEventWorker;
|
} InputEventWorker;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int Contents[8];
|
int contents[8]; // Key events FIFO contents (8 positions)
|
||||||
char Head;
|
char head; // Key events FIFO head position
|
||||||
char Tail;
|
char tail; // Key events FIFO tail position
|
||||||
} KeyEventFifo;
|
} KeyEventFifo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -498,7 +502,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData);
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
||||||
static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
|
static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
||||||
|
|
@ -703,7 +707,8 @@ void InitWindow(int width, int height, const char *title)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback);
|
// Detect fullscreen change events
|
||||||
|
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
||||||
|
|
||||||
// Support keyboard events
|
// Support keyboard events
|
||||||
emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||||
|
|
@ -867,9 +872,9 @@ bool IsWindowHidden(void)
|
||||||
// Toggle fullscreen mode (only PLATFORM_DESKTOP)
|
// Toggle fullscreen mode (only PLATFORM_DESKTOP)
|
||||||
void ToggleFullscreen(void)
|
void ToggleFullscreen(void)
|
||||||
{
|
{
|
||||||
#if defined(PLATFORM_DESKTOP)
|
|
||||||
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
|
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP)
|
||||||
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
|
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
|
||||||
if (CORE.Window.fullscreen)
|
if (CORE.Window.fullscreen)
|
||||||
{
|
{
|
||||||
|
|
@ -893,7 +898,10 @@ void ToggleFullscreen(void)
|
||||||
}
|
}
|
||||||
else glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
else glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
if (CORE.Window.fullscreen) EM_ASM(Module.requestFullscreen(false, false););
|
||||||
|
else EM_ASM(document.exitFullscreen(););
|
||||||
|
#endif
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||||
TRACELOG(LOG_WARNING, "Could not toggle to windowed mode");
|
TRACELOG(LOG_WARNING, "Could not toggle to windowed mode");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -971,6 +979,14 @@ void SetWindowSize(int width, int height)
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP)
|
||||||
glfwSetWindowSize(CORE.Window.handle, width, height);
|
glfwSetWindowSize(CORE.Window.handle, width, height);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
emscripten_set_canvas_size(width, height); // DEPRECATED!
|
||||||
|
|
||||||
|
// TODO: Below functions should be used to replace previous one but
|
||||||
|
// they do not seem to work properly
|
||||||
|
//emscripten_set_canvas_element_size("canvas", width, height);
|
||||||
|
//emscripten_set_element_css_size("canvas", width, height);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the window
|
// Show the window
|
||||||
|
|
@ -2168,80 +2184,84 @@ unsigned char *DecompressData(unsigned char *compData, int compDataLength, int *
|
||||||
|
|
||||||
// Save integer value to storage file (to defined position)
|
// Save integer value to storage file (to defined position)
|
||||||
// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer)
|
// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer)
|
||||||
void StorageSaveValue(int position, int value)
|
void SaveStorageValue(int position, int value)
|
||||||
{
|
{
|
||||||
FILE *storageFile = NULL;
|
#if defined(SUPPORT_DATA_STORAGE)
|
||||||
|
|
||||||
char path[512] = { 0 };
|
char path[512] = { 0 };
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
strcpy(path, CORE.Android.internalDataPath);
|
strcpy(path, CORE.Android.internalDataPath);
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, STORAGE_FILENAME);
|
strcat(path, STORAGE_DATA_FILE);
|
||||||
#else
|
#else
|
||||||
strcpy(path, STORAGE_FILENAME);
|
strcpy(path, STORAGE_DATA_FILE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Try open existing file to append data
|
int dataSize = 0;
|
||||||
storageFile = fopen(path, "rb+");
|
unsigned char *fileData = LoadFileData(path, &dataSize);
|
||||||
|
|
||||||
// If file doesn't exist, create a new storage data file
|
if (fileData != NULL)
|
||||||
if (!storageFile) storageFile = fopen(path, "wb");
|
{
|
||||||
|
if (dataSize <= (position*sizeof(int)))
|
||||||
if (!storageFile) TRACELOG(LOG_WARNING, "Storage data file could not be created");
|
{
|
||||||
|
// Increase data size up to position and store value
|
||||||
|
dataSize = (position + 1)*sizeof(int);
|
||||||
|
fileData = (unsigned char *)RL_REALLOC(fileData, dataSize);
|
||||||
|
int *dataPtr = (int *)fileData;
|
||||||
|
dataPtr[position] = value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get file size
|
// Replace value on selected position
|
||||||
fseek(storageFile, 0, SEEK_END);
|
int *dataPtr = (int *)fileData;
|
||||||
int fileSize = ftell(storageFile); // Size in bytes
|
dataPtr[position] = value;
|
||||||
fseek(storageFile, 0, SEEK_SET);
|
}
|
||||||
|
|
||||||
if (fileSize < (position*sizeof(int))) TRACELOG(LOG_WARNING, "Storage position could not be found");
|
SaveFileData(path, fileData, dataSize);
|
||||||
|
RL_FREE(fileData);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fseek(storageFile, (position*sizeof(int)), SEEK_SET);
|
dataSize = (position + 1)*sizeof(int);
|
||||||
fwrite(&value, 1, sizeof(int), storageFile);
|
fileData = (unsigned char *)RL_MALLOC(dataSize);
|
||||||
}
|
int *dataPtr = (int *)fileData;
|
||||||
|
dataPtr[position] = value;
|
||||||
|
|
||||||
fclose(storageFile);
|
SaveFileData(path, fileData, dataSize);
|
||||||
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load integer value from storage file (from defined position)
|
// Load integer value from storage file (from defined position)
|
||||||
// NOTE: If requested position could not be found, value 0 is returned
|
// NOTE: If requested position could not be found, value 0 is returned
|
||||||
int StorageLoadValue(int position)
|
int LoadStorageValue(int position)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
#if defined(SUPPORT_DATA_STORAGE)
|
||||||
char path[512] = { 0 };
|
char path[512] = { 0 };
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
strcpy(path, CORE.Android.internalDataPath);
|
strcpy(path, CORE.Android.internalDataPath);
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, STORAGE_FILENAME);
|
strcat(path, STORAGE_DATA_FILE);
|
||||||
#else
|
#else
|
||||||
strcpy(path, STORAGE_FILENAME);
|
strcpy(path, STORAGE_DATA_FILE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Try open existing file to append data
|
int dataSize = 0;
|
||||||
FILE *storageFile = fopen(path, "rb");
|
unsigned char *fileData = LoadFileData(path, &dataSize);
|
||||||
|
|
||||||
if (!storageFile) TRACELOG(LOG_WARNING, "Storage data file could not be found");
|
if (fileData != NULL)
|
||||||
|
{
|
||||||
|
if (dataSize < (position*4)) TRACELOG(LOG_WARNING, "Storage position could not be found");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get file size
|
int *dataPtr = (int *)fileData;
|
||||||
fseek(storageFile, 0, SEEK_END);
|
value = dataPtr[position];
|
||||||
int fileSize = ftell(storageFile); // Size in bytes
|
|
||||||
fseek(storageFile, 0, SEEK_SET); // Reset file pointer
|
|
||||||
|
|
||||||
if (fileSize < (position*4)) TRACELOG(LOG_WARNING, "Storage position could not be found");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fseek(storageFile, (position*4), SEEK_SET);
|
|
||||||
fread(&value, 4, 1, storageFile); // Read 1 element of 4 bytes size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(storageFile);
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2511,7 +2531,11 @@ bool IsMouseButtonReleased(int button)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
#if !defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
# if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
|
released = GetGestureDetected() == GESTURE_TAP;
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
|
if ((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
|
||||||
(GetMouseButtonStatus(button) == 0)) released = true;
|
(GetMouseButtonStatus(button) == 0)) released = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3574,12 +3598,12 @@ static void PollInputEvents(void)
|
||||||
for (int i = 0; i < 512; i++)CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
for (int i = 0; i < 512; i++)CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
||||||
|
|
||||||
// Grab a keypress from the evdev fifo if avalable
|
// Grab a keypress from the evdev fifo if avalable
|
||||||
if (CORE.Input.Keyboard.lastKeyPressed.Head != CORE.Input.Keyboard.lastKeyPressed.Tail)
|
if (CORE.Input.Keyboard.lastKeyPressed.head != CORE.Input.Keyboard.lastKeyPressed.tail)
|
||||||
{
|
{
|
||||||
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = CORE.Input.Keyboard.lastKeyPressed.Contents[CORE.Input.Keyboard.lastKeyPressed.Tail]; // Read the key from the buffer
|
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = CORE.Input.Keyboard.lastKeyPressed.contents[CORE.Input.Keyboard.lastKeyPressed.tail]; // Read the key from the buffer
|
||||||
CORE.Input.Keyboard.keyPressedQueueCount++;
|
CORE.Input.Keyboard.keyPressedQueueCount++;
|
||||||
|
|
||||||
CORE.Input.Keyboard.lastKeyPressed.Tail = (CORE.Input.Keyboard.lastKeyPressed.Tail + 1) & 0x07; // Increment the tail pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
CORE.Input.Keyboard.lastKeyPressed.tail = (CORE.Input.Keyboard.lastKeyPressed.tail + 1) & 0x07; // Increment the tail pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register previous mouse states
|
// Register previous mouse states
|
||||||
|
|
@ -4230,10 +4254,14 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
{
|
{
|
||||||
// If additional inputs are required check:
|
// If additional inputs are required check:
|
||||||
// https://developer.android.com/ndk/reference/group/input
|
// https://developer.android.com/ndk/reference/group/input
|
||||||
|
// https://developer.android.com/training/game-controllers/controller-input
|
||||||
|
|
||||||
int type = AInputEvent_getType(event);
|
int type = AInputEvent_getType(event);
|
||||||
|
int source = AInputEvent_getSource(event);
|
||||||
|
|
||||||
if (type == AINPUT_EVENT_TYPE_MOTION)
|
if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||||
|
{
|
||||||
|
if ((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK || (source & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD)
|
||||||
{
|
{
|
||||||
// Get first touch position
|
// Get first touch position
|
||||||
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
||||||
|
|
@ -4243,14 +4271,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
CORE.Input.Touch.position[1].x = AMotionEvent_getX(event, 1);
|
CORE.Input.Touch.position[1].x = AMotionEvent_getX(event, 1);
|
||||||
CORE.Input.Touch.position[1].y = AMotionEvent_getY(event, 1);
|
CORE.Input.Touch.position[1].y = AMotionEvent_getY(event, 1);
|
||||||
|
|
||||||
// Useful functions for gamepad inputs:
|
|
||||||
//AMotionEvent_getAction()
|
|
||||||
//AMotionEvent_getAxisValue()
|
|
||||||
//AMotionEvent_getButtonState()
|
|
||||||
|
|
||||||
// Gamepad dpad button presses capturing
|
|
||||||
// TODO: That's weird, key input (or button)
|
|
||||||
// shouldn't come as a TYPE_MOTION event...
|
|
||||||
int32_t keycode = AKeyEvent_getKeyCode(event);
|
int32_t keycode = AKeyEvent_getKeyCode(event);
|
||||||
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
||||||
{
|
{
|
||||||
|
|
@ -4261,6 +4281,57 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
}
|
}
|
||||||
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
|
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
|
||||||
|
|
||||||
|
// Stop processing gamepad buttons
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t action = AMotionEvent_getAction(event);
|
||||||
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
|
||||||
|
// Simple touch position
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_DOWN)
|
||||||
|
{
|
||||||
|
// Get first touch position
|
||||||
|
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
||||||
|
CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
|
GestureEvent gestureEvent;
|
||||||
|
|
||||||
|
// Register touch actions
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_DOWN;
|
||||||
|
else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_UP;
|
||||||
|
else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_MOVE;
|
||||||
|
|
||||||
|
// Register touch points count
|
||||||
|
// NOTE: Documentation says pointerCount is Always >= 1,
|
||||||
|
// but in practice it can be 0 or over a million
|
||||||
|
gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
|
||||||
|
|
||||||
|
// Only enable gestures for 1-3 touch points
|
||||||
|
if ((gestureEvent.pointCount > 0) && (gestureEvent.pointCount < 4))
|
||||||
|
{
|
||||||
|
// Register touch points id
|
||||||
|
// NOTE: Only two points registered
|
||||||
|
gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0);
|
||||||
|
gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1);
|
||||||
|
|
||||||
|
// Register touch points position
|
||||||
|
gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
|
||||||
|
gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
|
||||||
|
|
||||||
|
// Normalize gestureEvent.position[x] for screenWidth and screenHeight
|
||||||
|
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
||||||
|
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
||||||
|
|
||||||
|
gestureEvent.position[1].x /= (float)GetScreenWidth();
|
||||||
|
gestureEvent.position[1].y /= (float)GetScreenHeight();
|
||||||
|
|
||||||
|
// Gesture data is sent to gestures system for processing
|
||||||
|
ProcessGestureEvent(gestureEvent);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (type == AINPUT_EVENT_TYPE_KEY)
|
else if (type == AINPUT_EVENT_TYPE_KEY)
|
||||||
{
|
{
|
||||||
|
|
@ -4297,11 +4368,29 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
// Set default OS behaviour
|
// Set default OS behaviour
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t action = AMotionEvent_getAction(event);
|
int32_t action = AMotionEvent_getAction(event);
|
||||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
|
||||||
|
// Support only simple touch position
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_DOWN)
|
||||||
|
{
|
||||||
|
// Get first touch position
|
||||||
|
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
||||||
|
CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
|
||||||
|
}
|
||||||
|
else if (flags == AMOTION_EVENT_ACTION_UP)
|
||||||
|
{
|
||||||
|
// Get first touch position
|
||||||
|
CORE.Input.Touch.position[0].x = 0;
|
||||||
|
CORE.Input.Touch.position[0].y = 0;
|
||||||
|
}
|
||||||
|
else // TODO:Not sure what else should be handled
|
||||||
|
return 0;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
|
|
@ -4337,17 +4426,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
// Gesture data is sent to gestures system for processing
|
// Gesture data is sent to gestures system for processing
|
||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// Support only simple touch position
|
|
||||||
if (flags == AMOTION_EVENT_ACTION_DOWN)
|
|
||||||
{
|
|
||||||
// Get first touch position
|
|
||||||
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
|
||||||
CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
|
|
||||||
|
|
||||||
CORE.Input.Touch.position[0].x /= (float)GetScreenWidth();
|
|
||||||
CORE.Input.Touch.position[0].y /= (float)GetScreenHeight();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -4355,7 +4433,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
|
|
||||||
// Register fullscreen change events
|
// Register 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)
|
||||||
{
|
{
|
||||||
|
|
@ -4368,10 +4445,12 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte
|
||||||
|
|
||||||
if (event->isFullscreen)
|
if (event->isFullscreen)
|
||||||
{
|
{
|
||||||
|
CORE.Window.fullscreen = true;
|
||||||
TRACELOG(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
|
TRACELOG(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
CORE.Window.fullscreen = false;
|
||||||
TRACELOG(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
|
TRACELOG(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4688,8 +4767,8 @@ static void InitEvdevInput(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset keypress buffer
|
// Reset keypress buffer
|
||||||
CORE.Input.Keyboard.lastKeyPressed.Head = 0;
|
CORE.Input.Keyboard.lastKeyPressed.head = 0;
|
||||||
CORE.Input.Keyboard.lastKeyPressed.Tail = 0;
|
CORE.Input.Keyboard.lastKeyPressed.tail = 0;
|
||||||
|
|
||||||
// Reset keyboard key state
|
// Reset keyboard key state
|
||||||
for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
|
for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
|
||||||
|
|
@ -5052,8 +5131,8 @@ static void *EventThread(void *arg)
|
||||||
if (event.value > 0)
|
if (event.value > 0)
|
||||||
{
|
{
|
||||||
// Add the key int the fifo
|
// Add the key int the fifo
|
||||||
CORE.Input.Keyboard.lastKeyPressed.Contents[CORE.Input.Keyboard.lastKeyPressed.Head] = keycode; // Put the data at the front of the fifo snake
|
CORE.Input.Keyboard.lastKeyPressed.contents[CORE.Input.Keyboard.lastKeyPressed.head] = keycode; // Put the data at the front of the fifo snake
|
||||||
CORE.Input.Keyboard.lastKeyPressed.Head = (CORE.Input.Keyboard.lastKeyPressed.Head + 1) & 0x07; // Increment the head pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
CORE.Input.Keyboard.lastKeyPressed.head = (CORE.Input.Keyboard.lastKeyPressed.head + 1) & 0x07; // Increment the head pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
||||||
// TODO: This fifo is not fully threadsafe with multiple writers, so multiple keyboards hitting a key at the exact same time could miss a key (double write to head before it was incremented)
|
// TODO: This fifo is not fully threadsafe with multiple writers, so multiple keyboards hitting a key at the exact same time could miss a key (double write to head before it was incremented)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
12
src/models.c
12
src/models.c
|
|
@ -45,10 +45,10 @@
|
||||||
|
|
||||||
#include "utils.h" // Required for: fopen() Android mapping
|
#include "utils.h" // Required for: fopen() Android mapping
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free(), fabs()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
||||||
#include <string.h> // Required for: strncmp() [Used in LoadModelAnimations()], strlen() [Used in LoadTextureFromCgltfImage()]
|
#include <string.h> // Required for: strncmp() [Used in LoadModelAnimations()], strlen() [Used in LoadTextureFromCgltfImage()]
|
||||||
#include <math.h> // Required for: sinf(), cosf(), sqrtf()
|
#include <math.h> // Required for: sinf(), cosf(), sqrtf(), fabsf()
|
||||||
|
|
||||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||||
|
|
||||||
|
|
@ -2513,9 +2513,9 @@ void DrawBoundingBox(BoundingBox box, Color color)
|
||||||
{
|
{
|
||||||
Vector3 size;
|
Vector3 size;
|
||||||
|
|
||||||
size.x = (float)fabs(box.max.x - box.min.x);
|
size.x = fabsf(box.max.x - box.min.x);
|
||||||
size.y = (float)fabs(box.max.y - box.min.y);
|
size.y = fabsf(box.max.y - box.min.y);
|
||||||
size.z = (float)fabs(box.max.z - box.min.z);
|
size.z = fabsf(box.max.z - box.min.z);
|
||||||
|
|
||||||
Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };
|
Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };
|
||||||
|
|
||||||
|
|
@ -2761,7 +2761,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight)
|
||||||
|
|
||||||
RayHitInfo result = { 0 };
|
RayHitInfo result = { 0 };
|
||||||
|
|
||||||
if (fabs(ray.direction.y) > EPSILON)
|
if (fabsf(ray.direction.y) > EPSILON)
|
||||||
{
|
{
|
||||||
float distance = (ray.position.y - groundHeight)/-ray.direction.y;
|
float distance = (ray.position.y - groundHeight)/-ray.direction.y;
|
||||||
|
|
||||||
|
|
|
||||||
50
src/raudio.c
50
src/raudio.c
|
|
@ -165,6 +165,10 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
|
|
||||||
#if defined(RAUDIO_STANDALONE)
|
#if defined(RAUDIO_STANDALONE)
|
||||||
#include <string.h> // Required for: strcmp() [Used in IsFileExtension()]
|
#include <string.h> // Required for: strcmp() [Used in IsFileExtension()]
|
||||||
|
|
||||||
|
#if !defined(TRACELOG)
|
||||||
|
#define TRACELOG(level, ...) (void)0
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||||
|
|
@ -740,9 +744,8 @@ void ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
// Export raw sample data (without header)
|
// Export raw sample data (without header)
|
||||||
// NOTE: It's up to the user to track wave parameters
|
// NOTE: It's up to the user to track wave parameters
|
||||||
FILE *rawFile = fopen(fileName, "wb");
|
SaveFileData(fileName, wave.data, wave.sampleCount*wave.channels*wave.sampleSize/8);
|
||||||
success = fwrite(wave.data, wave.sampleCount*wave.channels*wave.sampleSize/8, 1, rawFile);
|
success = true;
|
||||||
fclose(rawFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) TRACELOG(LOG_INFO, "Wave exported successfully: %s", fileName);
|
if (success) TRACELOG(LOG_INFO, "Wave exported successfully: %s", fileName);
|
||||||
|
|
@ -1552,11 +1555,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
|
||||||
ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
|
ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
|
||||||
ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
|
ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
|
||||||
|
|
||||||
if (currentSubBufferIndex > 1)
|
if (currentSubBufferIndex > 1) return 0;
|
||||||
{
|
|
||||||
TRACELOGD("Frame cursor position moved too far forward in audio stream");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Another thread can update the processed state of buffers so
|
// Another thread can update the processed state of buffers so
|
||||||
// we just take a copy here to try and avoid potential synchronization problems
|
// we just take a copy here to try and avoid potential synchronization problems
|
||||||
|
|
@ -1704,13 +1703,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (framesRead > frameCount)
|
if (framesRead >= frameCount) break;
|
||||||
{
|
|
||||||
TRACELOGD("Mixed too many frames from audio buffer");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (framesRead == frameCount) break;
|
|
||||||
|
|
||||||
// Just read as much data as we can from the stream
|
// Just read as much data as we can from the stream
|
||||||
ma_uint32 framesToRead = (frameCount - framesRead);
|
ma_uint32 framesToRead = (frameCount - framesRead);
|
||||||
|
|
@ -2037,9 +2030,7 @@ static Wave LoadOGG(const char *fileName)
|
||||||
wave.data = (short *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(short));
|
wave.data = (short *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(short));
|
||||||
|
|
||||||
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
||||||
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels);
|
stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels);
|
||||||
TRACELOGD("[%s] Samples obtained: %i", fileName, numSamplesOgg);
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo");
|
TRACELOG(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo");
|
||||||
|
|
||||||
stb_vorbis_close(oggFile);
|
stb_vorbis_close(oggFile);
|
||||||
|
|
@ -2115,29 +2106,6 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
|
||||||
void TRACELOG(int msgType, const char *text, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, text);
|
|
||||||
|
|
||||||
switch (msgType)
|
|
||||||
{
|
|
||||||
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
|
||||||
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
|
||||||
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
|
||||||
case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfprintf(stdout, text, args);
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (msgType == LOG_ERROR) exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef AudioBuffer
|
#undef AudioBuffer
|
||||||
|
|
|
||||||
10
src/raylib.h
10
src/raylib.h
|
|
@ -107,10 +107,10 @@
|
||||||
#define RL_CALLOC(n,sz) calloc(n,sz)
|
#define RL_CALLOC(n,sz) calloc(n,sz)
|
||||||
#endif
|
#endif
|
||||||
#ifndef RL_REALLOC
|
#ifndef RL_REALLOC
|
||||||
#define RL_REALLOC(n,sz) realloc(n,sz)
|
#define RL_REALLOC(ptr,sz) realloc(ptr,sz)
|
||||||
#endif
|
#endif
|
||||||
#ifndef RL_FREE
|
#ifndef RL_FREE
|
||||||
#define RL_FREE(p) free(p)
|
#define RL_FREE(ptr) free(ptr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
|
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
|
||||||
|
|
@ -949,6 +949,8 @@ RLAPI void TakeScreenshot(const char *fileName); // Takes a scr
|
||||||
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *bytesRead); // Load file data as byte array (read)
|
||||||
|
RLAPI void SaveFileData(const char *fileName, void *data, int bytesToWrite); // Save data to file from byte array (write)
|
||||||
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
|
||||||
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
||||||
|
|
@ -970,8 +972,8 @@ RLAPI unsigned char *CompressData(unsigned char *data, int dataLength, int *comp
|
||||||
RLAPI unsigned char *DecompressData(unsigned char *compData, int compDataLength, int *dataLength); // Decompress data (DEFLATE algorythm)
|
RLAPI unsigned char *DecompressData(unsigned char *compData, int compDataLength, int *dataLength); // Decompress data (DEFLATE algorythm)
|
||||||
|
|
||||||
// Persistent storage management
|
// Persistent storage management
|
||||||
RLAPI void StorageSaveValue(int position, int value); // Save integer value to storage file (to defined position)
|
RLAPI void SaveStorageValue(int position, int value); // Save integer value to storage file (to defined position)
|
||||||
RLAPI int StorageLoadValue(int position); // Load integer value from storage file (from defined position)
|
RLAPI int LoadStorageValue(int position); // Load integer value from storage file (from defined position)
|
||||||
|
|
||||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1135,8 +1135,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||||
else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
|
else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float halfTheta = (float) acos(cosHalfTheta);
|
float halfTheta = acosf(cosHalfTheta);
|
||||||
float sinHalfTheta = (float) sqrt(1.0f - cosHalfTheta*cosHalfTheta);
|
float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
|
||||||
|
|
||||||
if (fabs(sinHalfTheta) < 0.001f)
|
if (fabs(sinHalfTheta) < 0.001f)
|
||||||
{
|
{
|
||||||
|
|
@ -1191,7 +1191,7 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix mat)
|
||||||
|
|
||||||
if (trace > 0.0f)
|
if (trace > 0.0f)
|
||||||
{
|
{
|
||||||
float s = (float)sqrt(trace + 1)*2.0f;
|
float s = sqrtf(trace + 1)*2.0f;
|
||||||
float invS = 1.0f/s;
|
float invS = 1.0f/s;
|
||||||
|
|
||||||
result.w = s*0.25f;
|
result.w = s*0.25f;
|
||||||
|
|
@ -1215,7 +1215,7 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix mat)
|
||||||
}
|
}
|
||||||
else if (m11 > m22)
|
else if (m11 > m22)
|
||||||
{
|
{
|
||||||
float s = (float)sqrt(1.0f + m11 - m00 - m22)*2.0f;
|
float s = sqrtf(1.0f + m11 - m00 - m22)*2.0f;
|
||||||
float invS = 1.0f/s;
|
float invS = 1.0f/s;
|
||||||
|
|
||||||
result.w = (mat.m8 - mat.m2)*invS;
|
result.w = (mat.m8 - mat.m2)*invS;
|
||||||
|
|
@ -1225,7 +1225,7 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix mat)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float s = (float)sqrt(1.0f + m22 - m00 - m11)*2.0f;
|
float s = sqrtf(1.0f + m22 - m00 - m11)*2.0f;
|
||||||
float invS = 1.0f/s;
|
float invS = 1.0f/s;
|
||||||
|
|
||||||
result.w = (mat.m1 - mat.m4)*invS;
|
result.w = (mat.m1 - mat.m4)*invS;
|
||||||
|
|
@ -1317,8 +1317,8 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle
|
||||||
Vector3 resAxis = { 0.0f, 0.0f, 0.0f };
|
Vector3 resAxis = { 0.0f, 0.0f, 0.0f };
|
||||||
float resAngle = 0.0f;
|
float resAngle = 0.0f;
|
||||||
|
|
||||||
resAngle = 2.0f*(float)acos(q.w);
|
resAngle = 2.0f*acosf(q.w);
|
||||||
float den = (float)sqrt(1.0f - q.w*q.w);
|
float den = sqrtf(1.0f - q.w*q.w);
|
||||||
|
|
||||||
if (den > 0.0001f)
|
if (den > 0.0001f)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
59
src/rlgl.h
59
src/rlgl.h
|
|
@ -76,15 +76,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Support TRACELOG macros
|
// Support TRACELOG macros
|
||||||
#if defined(RLGL_SUPPORT_TRACELOG)
|
#if !defined(TRACELOG)
|
||||||
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
|
|
||||||
|
|
||||||
#if defined(RLGL_SUPPORT_TRACELOG_DEBUG)
|
|
||||||
#define TRACELOGD(...) TraceLog(LOG_DEBUG, __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define TRACELOGD(...) (void)0
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define TRACELOG(level, ...) (void)0
|
#define TRACELOG(level, ...) (void)0
|
||||||
#define TRACELOGD(...) (void)0
|
#define TRACELOGD(...) (void)0
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -596,7 +588,6 @@ RLAPI void ToggleVrMode(void); // Enable/Disable VR exp
|
||||||
RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering
|
RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering
|
||||||
RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering
|
RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering
|
||||||
|
|
||||||
RLAPI void TRACELOG(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
|
||||||
RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data size in bytes (image or texture)
|
RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data size in bytes (image or texture)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -621,10 +612,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free(), fabs()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
#include <stdio.h> // Required for: fopen(), fseek(), fread(), fclose() [LoadText]
|
#include <stdio.h> // Required for: fopen(), fseek(), fread(), fclose() [LoadText]
|
||||||
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
||||||
#include <math.h> // Required for: atan2f()
|
#include <math.h> // Required for: atan2f(), fabs()
|
||||||
|
|
||||||
#if !defined(RLGL_STANDALONE)
|
#if !defined(RLGL_STANDALONE)
|
||||||
#include "raymath.h" // Required for: Vector3 and Matrix functions
|
#include "raymath.h" // Required for: Vector3 and Matrix functions
|
||||||
|
|
@ -676,10 +667,6 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data
|
||||||
#include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
|
#include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RLGL_STANDALONE)
|
|
||||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [Used in TraceLog()]
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -3001,15 +2988,17 @@ Shader GetShaderDefault(void)
|
||||||
// NOTE: text chars array should be freed manually
|
// NOTE: text chars array should be freed manually
|
||||||
char *LoadText(const char *fileName)
|
char *LoadText(const char *fileName)
|
||||||
{
|
{
|
||||||
FILE *textFile = NULL;
|
|
||||||
char *text = NULL;
|
char *text = NULL;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
textFile = fopen(fileName,"rt");
|
FILE *textFile = fopen(fileName, "rt");
|
||||||
|
|
||||||
if (textFile != NULL)
|
if (textFile != NULL)
|
||||||
{
|
{
|
||||||
|
// WARNING: When reading a file as 'text' file,
|
||||||
|
// text mode causes carriage return-linefeed translation...
|
||||||
|
// ...but using fseek() should return correct byte-offset
|
||||||
fseek(textFile, 0, SEEK_END);
|
fseek(textFile, 0, SEEK_END);
|
||||||
int size = ftell(textFile);
|
int size = ftell(textFile);
|
||||||
fseek(textFile, 0, SEEK_SET);
|
fseek(textFile, 0, SEEK_SET);
|
||||||
|
|
@ -3018,6 +3007,15 @@ char *LoadText(const char *fileName)
|
||||||
{
|
{
|
||||||
text = (char *)RL_MALLOC(sizeof(char)*(size + 1));
|
text = (char *)RL_MALLOC(sizeof(char)*(size + 1));
|
||||||
int count = fread(text, sizeof(char), size, textFile);
|
int count = fread(text, sizeof(char), size, textFile);
|
||||||
|
|
||||||
|
// WARNING: \r\n is converted to \n on reading, so,
|
||||||
|
// read bytes count gets reduced by the number of lines
|
||||||
|
if (count < size)
|
||||||
|
{
|
||||||
|
text = RL_REALLOC(text, count + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero-terminate the string
|
||||||
text[count] = '\0';
|
text[count] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3664,7 +3662,7 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
|
||||||
|
|
||||||
// Compute distortion scale parameters
|
// Compute distortion scale parameters
|
||||||
// NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
|
// NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
|
||||||
float lensRadius = (float)fabs(-1.0f - 4.0f*lensShift);
|
float lensRadius = fabsf(-1.0f - 4.0f*lensShift);
|
||||||
float lensRadiusSq = lensRadius*lensRadius;
|
float lensRadiusSq = lensRadius*lensRadius;
|
||||||
float distortionScale = hmd.lensDistortionValues[0] +
|
float distortionScale = hmd.lensDistortionValues[0] +
|
||||||
hmd.lensDistortionValues[1]*lensRadiusSq +
|
hmd.lensDistortionValues[1]*lensRadiusSq +
|
||||||
|
|
@ -4645,29 +4643,6 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
|
||||||
void TraceLog(int msgType, const char *text, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, text);
|
|
||||||
|
|
||||||
switch (msgType)
|
|
||||||
{
|
|
||||||
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
|
||||||
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
|
||||||
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
|
||||||
case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfprintf(stdout, text, args);
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (msgType == LOG_ERROR) exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pixel data size in bytes (image or texture)
|
// Get pixel data size in bytes (image or texture)
|
||||||
// NOTE: Size depends on pixel format
|
// NOTE: Size depends on pixel format
|
||||||
int GetPixelDataSize(int width, int height, int format)
|
int GetPixelDataSize(int width, int height, int format)
|
||||||
|
|
|
||||||
11
src/shapes.c
11
src/shapes.c
|
|
@ -42,8 +42,7 @@
|
||||||
|
|
||||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: fabs()
|
#include <math.h> // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf()
|
||||||
#include <math.h> // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf()
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
|
|
@ -1471,8 +1470,8 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||||
int recCenterX = (int)(rec.x + rec.width/2.0f);
|
int recCenterX = (int)(rec.x + rec.width/2.0f);
|
||||||
int recCenterY = (int)(rec.y + rec.height/2.0f);
|
int recCenterY = (int)(rec.y + rec.height/2.0f);
|
||||||
|
|
||||||
float dx = (float)fabs(center.x - recCenterX);
|
float dx = fabsf(center.x - (float)recCenterX);
|
||||||
float dy = (float)fabs(center.y - recCenterY);
|
float dy = fabsf(center.y - (float)recCenterY);
|
||||||
|
|
||||||
if (dx > (rec.width/2.0f + radius)) { return false; }
|
if (dx > (rec.width/2.0f + radius)) { return false; }
|
||||||
if (dy > (rec.height/2.0f + radius)) { return false; }
|
if (dy > (rec.height/2.0f + radius)) { return false; }
|
||||||
|
|
@ -1493,8 +1492,8 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
||||||
|
|
||||||
if (CheckCollisionRecs(rec1, rec2))
|
if (CheckCollisionRecs(rec1, rec2))
|
||||||
{
|
{
|
||||||
float dxx = (float)fabs(rec1.x - rec2.x);
|
float dxx = fabsf(rec1.x - rec2.x);
|
||||||
float dyy = (float)fabs(rec1.y - rec2.y);
|
float dyy = fabsf(rec1.y - rec2.y);
|
||||||
|
|
||||||
if (rec1.x <= rec2.x)
|
if (rec1.x <= rec2.x)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -241,8 +241,8 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
|
||||||
canvas: (function() {
|
canvas: (function() {
|
||||||
var canvas = document.querySelector('#canvas');
|
var canvas = document.querySelector('#canvas');
|
||||||
|
|
||||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
// As a default initial behavior, pop up an alert when webgl context is lost.
|
||||||
// application robust, you may want to override this behavior before shipping!
|
// To make your application robust, you may want to override this behavior before shipping!
|
||||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||||
|
|
||||||
|
|
|
||||||
30
src/text.c
30
src/text.c
|
|
@ -333,11 +333,11 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.charsCount = (charsCount > 0)? charsCount : 95;
|
font.charsCount = (charsCount > 0)? charsCount : 95;
|
||||||
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
|
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
|
||||||
if (font.chars != NULL)
|
if (font.chars != NULL)
|
||||||
{
|
{
|
||||||
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, 2, 0);
|
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, 2, 0);
|
||||||
|
|
@ -354,7 +354,6 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
|
||||||
}
|
}
|
||||||
else font = GetFontDefault();
|
else font = GetFontDefault();
|
||||||
#else
|
#else
|
||||||
UnloadFont(font);
|
|
||||||
font = GetFontDefault();
|
font = GetFontDefault();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -498,24 +497,16 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
// Load font data (including pixel data) from TTF file
|
// Load font data (including pixel data) from TTF file
|
||||||
// NOTE: Loaded information should be enough to generate font image atlas,
|
// NOTE: Loaded information should be enough to generate
|
||||||
// using any packaging method
|
// font image atlas, using any packaging method
|
||||||
FILE *fontFile = fopen(fileName, "rb"); // Load font file
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fontFile != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
fseek(fontFile, 0, SEEK_END);
|
|
||||||
long size = ftell(fontFile); // Get file size
|
|
||||||
fseek(fontFile, 0, SEEK_SET); // Reset file pointer
|
|
||||||
|
|
||||||
unsigned char *fontBuffer = (unsigned char *)RL_MALLOC(size);
|
|
||||||
|
|
||||||
fread(fontBuffer, size, 1, fontFile);
|
|
||||||
fclose(fontFile);
|
|
||||||
|
|
||||||
// Init font for data reading
|
// Init font for data reading
|
||||||
stbtt_fontinfo fontInfo;
|
stbtt_fontinfo fontInfo;
|
||||||
if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TRACELOG(LOG_WARNING, "Failed to init font!");
|
if (!stbtt_InitFont(&fontInfo, fileData, 0)) TRACELOG(LOG_WARNING, "Failed to init font!");
|
||||||
|
|
||||||
// Calculate font scale factor
|
// Calculate font scale factor
|
||||||
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
|
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
|
||||||
|
|
@ -595,12 +586,9 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
RL_FREE(fontBuffer);
|
RL_FREE(fileData);
|
||||||
if (genFontChars) RL_FREE(fontChars);
|
if (genFontChars) RL_FREE(fontChars);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "[%s] TTF file could not be opened", fileName);
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_WARNING, "[%s] TTF support is disabled", fileName);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return chars;
|
return chars;
|
||||||
|
|
@ -1149,6 +1137,7 @@ const char *TextFormat(const char *text, ...)
|
||||||
static int index = 0;
|
static int index = 0;
|
||||||
|
|
||||||
char *currentBuffer = buffers[index];
|
char *currentBuffer = buffers[index];
|
||||||
|
memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
|
|
@ -1655,7 +1644,6 @@ static Font LoadBMFont(const char *fileName)
|
||||||
#define MAX_BUFFER_SIZE 256
|
#define MAX_BUFFER_SIZE 256
|
||||||
|
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
font.texture.id = 0;
|
|
||||||
|
|
||||||
char buffer[MAX_BUFFER_SIZE] = { 0 };
|
char buffer[MAX_BUFFER_SIZE] = { 0 };
|
||||||
char *searchPoint = NULL;
|
char *searchPoint = NULL;
|
||||||
|
|
|
||||||
135
src/textures.c
135
src/textures.c
|
|
@ -64,9 +64,10 @@
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free(), fabs()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
|
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
|
||||||
#include <string.h> // Required for: strlen() [Used in ImageTextEx()]
|
#include <string.h> // Required for: strlen() [Used in ImageTextEx()]
|
||||||
|
#include <math.h> // Required for: fabsf()
|
||||||
|
|
||||||
#include "utils.h" // Required for: fopen() Android mapping
|
#include "utils.h" // Required for: fopen() Android mapping
|
||||||
|
|
||||||
|
|
@ -195,6 +196,7 @@ Image LoadImage(const char *fileName)
|
||||||
defined(SUPPORT_FILEFORMAT_TGA) || \
|
defined(SUPPORT_FILEFORMAT_TGA) || \
|
||||||
defined(SUPPORT_FILEFORMAT_GIF) || \
|
defined(SUPPORT_FILEFORMAT_GIF) || \
|
||||||
defined(SUPPORT_FILEFORMAT_PIC) || \
|
defined(SUPPORT_FILEFORMAT_PIC) || \
|
||||||
|
defined(SUPPORT_FILEFORMAT_HDR) || \
|
||||||
defined(SUPPORT_FILEFORMAT_PSD)
|
defined(SUPPORT_FILEFORMAT_PSD)
|
||||||
#define STBI_REQUIRED
|
#define STBI_REQUIRED
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -225,53 +227,53 @@ Image LoadImage(const char *fileName)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#if defined(STBI_REQUIRED)
|
#if defined(STBI_REQUIRED)
|
||||||
int imgWidth = 0;
|
|
||||||
int imgHeight = 0;
|
|
||||||
int imgBpp = 0;
|
|
||||||
|
|
||||||
FILE *imFile = fopen(fileName, "rb");
|
|
||||||
|
|
||||||
if (imFile != NULL)
|
|
||||||
{
|
|
||||||
// NOTE: Using stb_image to load images (Supports multiple image formats)
|
// NOTE: Using stb_image to load images (Supports multiple image formats)
|
||||||
image.data = stbi_load_from_file(imFile, &imgWidth, &imgHeight, &imgBpp, 0);
|
|
||||||
|
|
||||||
fclose(imFile);
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
|
if (fileData != NULL)
|
||||||
|
{
|
||||||
|
int comp = 0;
|
||||||
|
image.data = stbi_load_from_memory(fileData, dataSize, &image.width, &image.height, &comp, 0);
|
||||||
|
|
||||||
image.width = imgWidth;
|
|
||||||
image.height = imgHeight;
|
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
|
|
||||||
if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE;
|
if (comp == 1) image.format = UNCOMPRESSED_GRAYSCALE;
|
||||||
else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA;
|
else if (comp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA;
|
||||||
else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8;
|
else if (comp == 3) image.format = UNCOMPRESSED_R8G8B8;
|
||||||
else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8;
|
else if (comp == 4) image.format = UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
||||||
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined(SUPPORT_FILEFORMAT_HDR)
|
#if defined(SUPPORT_FILEFORMAT_HDR)
|
||||||
else if (IsFileExtension(fileName, ".hdr"))
|
else if (IsFileExtension(fileName, ".hdr"))
|
||||||
{
|
{
|
||||||
int imgBpp = 0;
|
#if defined(STBI_REQUIRED)
|
||||||
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
FILE *imFile = fopen(fileName, "rb");
|
if (fileData != NULL)
|
||||||
|
{
|
||||||
// Load 32 bit per channel floats data
|
int comp = 0;
|
||||||
//stbi_set_flip_vertically_on_load(true);
|
image.data = stbi_loadf_from_memory(fileData, dataSize, &image.width, &image.height, &comp, 0);
|
||||||
image.data = stbi_loadf_from_file(imFile, &image.width, &image.height, &imgBpp, 0);
|
|
||||||
|
|
||||||
fclose(imFile);
|
|
||||||
|
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
|
|
||||||
if (imgBpp == 1) image.format = UNCOMPRESSED_R32;
|
if (comp == 1) image.format = UNCOMPRESSED_R32;
|
||||||
else if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32;
|
else if (comp == 3) image.format = UNCOMPRESSED_R32G32B32;
|
||||||
else if (imgBpp == 4) image.format = UNCOMPRESSED_R32G32B32A32;
|
else if (comp == 4) image.format = UNCOMPRESSED_R32G32B32A32;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "[%s] Image fileformat not supported", fileName);
|
TRACELOG(LOG_WARNING, "[%s] HDR Image fileformat not supported", fileName);
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RL_FREE(fileData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_DDS)
|
#if defined(SUPPORT_FILEFORMAT_DDS)
|
||||||
|
|
@ -346,40 +348,24 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
|
|
||||||
FILE *rawFile = fopen(fileName, "rb");
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (rawFile == NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "[%s] RAW image file could not be opened", fileName);
|
unsigned char *dataPtr = fileData;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
|
|
||||||
|
|
||||||
unsigned int size = GetPixelDataSize(width, height, format);
|
unsigned int size = GetPixelDataSize(width, height, format);
|
||||||
|
|
||||||
|
if (headerSize > 0) dataPtr += headerSize;
|
||||||
|
|
||||||
image.data = RL_MALLOC(size); // Allocate required memory in bytes
|
image.data = RL_MALLOC(size); // Allocate required memory in bytes
|
||||||
|
memcpy(image.data, dataPtr, size); // Copy required data to image
|
||||||
// NOTE: fread() returns num read elements instead of bytes,
|
|
||||||
// to get bytes we need to read (1 byte size, elements) instead of (x byte size, 1 element)
|
|
||||||
int bytes = fread(image.data, 1, size, rawFile);
|
|
||||||
|
|
||||||
// Check if data has been read successfully
|
|
||||||
if (bytes < size)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName);
|
|
||||||
|
|
||||||
RL_FREE(image.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image.width = width;
|
image.width = width;
|
||||||
image.height = height;
|
image.height = height;
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
image.format = format;
|
image.format = format;
|
||||||
}
|
|
||||||
|
|
||||||
fclose(rawFile);
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
|
|
@ -844,9 +830,8 @@ void ExportImage(Image image, const char *fileName)
|
||||||
{
|
{
|
||||||
// Export raw pixel data (without header)
|
// Export raw pixel data (without header)
|
||||||
// NOTE: It's up to the user to track image parameters
|
// NOTE: It's up to the user to track image parameters
|
||||||
FILE *rawFile = fopen(fileName, "wb");
|
SaveFileData(fileName, image.data, GetPixelDataSize(image.width, image.height, image.format));
|
||||||
success = fwrite(image.data, GetPixelDataSize(image.width, image.height, image.format), 1, rawFile);
|
success = true;
|
||||||
fclose(rawFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RL_FREE(imgData);
|
RL_FREE(imgData);
|
||||||
|
|
@ -2704,7 +2689,7 @@ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float sc
|
||||||
// Draw a part of a texture (defined by a rectangle)
|
// Draw a part of a texture (defined by a rectangle)
|
||||||
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
|
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
|
||||||
{
|
{
|
||||||
Rectangle destRec = { position.x, position.y, (float)fabs(sourceRec.width), (float)fabs(sourceRec.height) };
|
Rectangle destRec = { position.x, position.y, fabsf(sourceRec.width), fabsf(sourceRec.height) };
|
||||||
Vector2 origin = { 0.0f, 0.0f };
|
Vector2 origin = { 0.0f, 0.0f };
|
||||||
|
|
||||||
DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint);
|
DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint);
|
||||||
|
|
@ -2983,30 +2968,18 @@ static Image LoadAnimatedGIF(const char *fileName, int *frames, int **delays)
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
|
|
||||||
FILE *gifFile = fopen(fileName, "rb");
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (gifFile == NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "[%s] Animated GIF file could not be opened", fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fseek(gifFile, 0L, SEEK_END);
|
|
||||||
int size = ftell(gifFile);
|
|
||||||
fseek(gifFile, 0L, SEEK_SET);
|
|
||||||
|
|
||||||
unsigned char *buffer = (unsigned char *)RL_CALLOC(size, sizeof(char));
|
|
||||||
fread(buffer, sizeof(char), size, gifFile);
|
|
||||||
|
|
||||||
fclose(gifFile); // Close file pointer
|
|
||||||
|
|
||||||
int comp = 0;
|
int comp = 0;
|
||||||
image.data = stbi_load_gif_from_memory(buffer, size, delays, &image.width, &image.height, frames, &comp, 4);
|
image.data = stbi_load_gif_from_memory(fileData, dataSize, delays, &image.width, &image.height, frames, &comp, 4);
|
||||||
|
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
image.format = UNCOMPRESSED_R8G8B8A8;
|
image.format = UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
||||||
free(buffer);
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
|
|
@ -3071,7 +3044,7 @@ static Image LoadDDS(const char *fileName)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Verify the type of file
|
// Verify the type of file
|
||||||
char ddsHeaderId[4];
|
char ddsHeaderId[4] = { 0 };
|
||||||
|
|
||||||
fread(ddsHeaderId, 4, 1, ddsFile);
|
fread(ddsHeaderId, 4, 1, ddsFile);
|
||||||
|
|
||||||
|
|
@ -3081,7 +3054,7 @@ static Image LoadDDS(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DDSHeader ddsHeader;
|
DDSHeader ddsHeader = { 0 };
|
||||||
|
|
||||||
// Get the image header
|
// Get the image header
|
||||||
fread(&ddsHeader, sizeof(DDSHeader), 1, ddsFile);
|
fread(&ddsHeader, sizeof(DDSHeader), 1, ddsFile);
|
||||||
|
|
@ -3250,7 +3223,7 @@ static Image LoadPKM(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PKMHeader pkmHeader;
|
PKMHeader pkmHeader = { 0 };
|
||||||
|
|
||||||
// Get the image header
|
// Get the image header
|
||||||
fread(&pkmHeader, sizeof(PKMHeader), 1, pkmFile);
|
fread(&pkmHeader, sizeof(PKMHeader), 1, pkmFile);
|
||||||
|
|
@ -3343,7 +3316,7 @@ static Image LoadKTX(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KTXHeader ktxHeader;
|
KTXHeader ktxHeader = { 0 };
|
||||||
|
|
||||||
// Get the image header
|
// Get the image header
|
||||||
fread(&ktxHeader, sizeof(KTXHeader), 1, ktxFile);
|
fread(&ktxHeader, sizeof(KTXHeader), 1, ktxFile);
|
||||||
|
|
@ -3424,7 +3397,7 @@ static int SaveKTX(Image image, const char *fileName)
|
||||||
if (ktxFile == NULL) TRACELOG(LOG_WARNING, "[%s] KTX image file could not be created", fileName);
|
if (ktxFile == NULL) TRACELOG(LOG_WARNING, "[%s] KTX image file could not be created", fileName);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KTXHeader ktxHeader;
|
KTXHeader ktxHeader = { 0 };
|
||||||
|
|
||||||
// KTX identifier (v1.1)
|
// KTX identifier (v1.1)
|
||||||
//unsigned char id[12] = { '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' };
|
//unsigned char id[12] = { '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' };
|
||||||
|
|
@ -3560,7 +3533,7 @@ static Image LoadPVR(const char *fileName)
|
||||||
// Load different PVR data formats
|
// Load different PVR data formats
|
||||||
if (pvrVersion == 0x50)
|
if (pvrVersion == 0x50)
|
||||||
{
|
{
|
||||||
PVRHeaderV3 pvrHeader;
|
PVRHeaderV3 pvrHeader = { 0 };
|
||||||
|
|
||||||
// Get PVR image header
|
// Get PVR image header
|
||||||
fread(&pvrHeader, sizeof(PVRHeaderV3), 1, pvrFile);
|
fread(&pvrHeader, sizeof(PVRHeaderV3), 1, pvrFile);
|
||||||
|
|
@ -3670,7 +3643,7 @@ static Image LoadASTC(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASTCHeader astcHeader;
|
ASTCHeader astcHeader = { 0 };
|
||||||
|
|
||||||
// Get ASTC image header
|
// Get ASTC image header
|
||||||
fread(&astcHeader, sizeof(ASTCHeader), 1, astcFile);
|
fread(&astcHeader, sizeof(ASTCHeader), 1, astcFile);
|
||||||
|
|
|
||||||
53
src/utils.c
53
src/utils.c
|
|
@ -163,6 +163,59 @@ void TraceLog(int logType, const char *text, ...)
|
||||||
#endif // SUPPORT_TRACELOG
|
#endif // SUPPORT_TRACELOG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load data from file into a buffer
|
||||||
|
unsigned char *LoadFileData(const char *fileName, int *bytesRead)
|
||||||
|
{
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
*bytesRead = 0;
|
||||||
|
|
||||||
|
FILE *file = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
// WARNING: On binary streams SEEK_END could not be found,
|
||||||
|
// using fseek() and ftell() could not work in some (rare) cases
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
int size = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
data = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*size);
|
||||||
|
|
||||||
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
|
int count = fread(data, sizeof(unsigned char), size, file);
|
||||||
|
*bytesRead = count;
|
||||||
|
|
||||||
|
if (count != size) TRACELOG(LOG_WARNING, "[%s] File partially loaded", fileName);
|
||||||
|
else TRACELOG(LOG_INFO, "[%s] File loaded successfully", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] File could not be read", fileName);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save data to file from buffer
|
||||||
|
void SaveFileData(const char *fileName, void *data, int bytesToWrite)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
int count = fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
||||||
|
|
||||||
|
if (count == 0) TRACELOG(LOG_WARNING, "[%s] File could not be written", fileName);
|
||||||
|
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "[%s] File partially written", fileName);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
// Initialize asset manager from android app
|
// Initialize asset manager from android app
|
||||||
void InitAssetManager(AAssetManager *manager)
|
void InitAssetManager(AAssetManager *manager)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user