Merging master (#3)
* REDESIGNED input system for better mouse/touch support * Update Makefile * Reviewed IsMouseButtonDown() * Added comment on IsMouseButtonDown() issue IsMouseButtonDown() does not process touch state down properly, state is reseted every frame... * Update textures_mouse_painting.c * Update raymath.h (#1118) * Update raymath.h Added Vector2Rotate Function. * Update raymath.h * Support touch drawing on web * Review some comment * Review shader exaples to work on web (GLSL 100) * Support any mouse button for gesture detection * Some code tweaks * REVIEWED: Mouse/Touch input system After several reviews, now it seems everything works as expected. * Avoid icons in shell Very weird... lately icons are not properly displayed on browser! * Update core.c * WARNING: Corrected issue with IsKeyDown() #1119 * ADDED: LoadFileText() and SaveFileText() Improved file access checks Co-authored-by: Ray <raysan5@gmail.com> Co-authored-by: i-right-i <olmstead.ben@gmail.com>
This commit is contained in:
parent
da6b05e15c
commit
035826a37b
|
|
@ -118,7 +118,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
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ in vec3 fragPosition;
|
||||||
uniform samplerCube environmentMap;
|
uniform samplerCube environmentMap;
|
||||||
|
|
||||||
// Constant values
|
// Constant values
|
||||||
const float PI = 3.14159265359f;
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
// Output fragment color
|
// Output fragment color
|
||||||
out vec4 finalColor;
|
out vec4 finalColor;
|
||||||
|
|
@ -31,8 +31,8 @@ void main()
|
||||||
vec3 right = cross(up, normal);
|
vec3 right = cross(up, normal);
|
||||||
up = cross(normal, right);
|
up = cross(normal, right);
|
||||||
|
|
||||||
float sampleDelta = 0.025f;
|
float sampleDelta = 0.025;
|
||||||
float nrSamples = 0.0f;
|
float nrSamples = 0.0;
|
||||||
|
|
||||||
for (float phi = 0.0; phi < 2.0*PI; phi += sampleDelta)
|
for (float phi = 0.0; phi < 2.0*PI; phi += sampleDelta)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ void main()
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
|
||||||
// Calculate fragment position based on model transformations
|
// Calculate fragment position based on model transformations
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
|
||||||
// Send vertex attributes to fragment shader
|
// Send vertex attributes to fragment shader
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ uniform samplerCube environmentMap;
|
||||||
uniform float roughness;
|
uniform float roughness;
|
||||||
|
|
||||||
// Constant values
|
// Constant values
|
||||||
const float PI = 3.14159265359f;
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
// Output fragment color
|
// Output fragment color
|
||||||
out vec4 finalColor;
|
out vec4 finalColor;
|
||||||
|
|
@ -35,7 +35,7 @@ float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
float NdotH = max(dot(N, H), 0.0);
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
float NdotH2 = NdotH*NdotH;
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
float nom = a2;
|
float nom = a2;
|
||||||
float denom = (NdotH2*(a2 - 1.0) + 1.0);
|
float denom = (NdotH2*(a2 - 1.0) + 1.0);
|
||||||
denom = PI*denom*denom;
|
denom = PI*denom*denom;
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ float RadicalInverse_VdC(uint bits)
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
return float(bits)*2.3283064365386963e-10; // / 0x100000000
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 Hammersley(uint i, uint N)
|
vec2 Hammersley(uint i, uint N)
|
||||||
|
|
@ -60,7 +60,7 @@ vec2 Hammersley(uint i, uint N)
|
||||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
||||||
{
|
{
|
||||||
float a = roughness*roughness;
|
float a = roughness*roughness;
|
||||||
float phi = 2.0 * PI * Xi.x;
|
float phi = 2.0*PI*Xi.x;
|
||||||
float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y));
|
float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y));
|
||||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ uniform sampler2D texture0;
|
||||||
uniform vec4 colDiffuse;
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
// NOTE: Add here your custom variables
|
// NOTE: Add here your custom variables
|
||||||
uniform vec2 resolution = vec2(800, 450);
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
59
examples/shaders/resources/shaders/glsl100/base_lighting.vs
Normal file
59
examples/shaders/resources/shaders/glsl100/base_lighting.vs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#version 100
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
attribute vec3 vertexPosition;
|
||||||
|
attribute vec2 vertexTexCoord;
|
||||||
|
attribute vec3 vertexNormal;
|
||||||
|
attribute vec4 vertexColor;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 matModel;
|
||||||
|
|
||||||
|
// Output vertex attributes (to fragment shader)
|
||||||
|
varying vec3 fragPosition;
|
||||||
|
varying vec2 fragTexCoord;
|
||||||
|
varying vec4 fragColor;
|
||||||
|
varying vec3 fragNormal;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
// https://github.com/glslify/glsl-inverse
|
||||||
|
mat3 inverse(mat3 m)
|
||||||
|
{
|
||||||
|
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
|
||||||
|
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
|
||||||
|
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
|
||||||
|
|
||||||
|
float b01 = a22*a11 - a12*a21;
|
||||||
|
float b11 = -a22*a10 + a12*a20;
|
||||||
|
float b21 = a21*a10 - a11*a20;
|
||||||
|
|
||||||
|
float det = a00*b01 + a01*b11 + a02*b21;
|
||||||
|
|
||||||
|
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
|
||||||
|
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
|
||||||
|
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/glslify/glsl-transpose
|
||||||
|
mat3 transpose(mat3 m)
|
||||||
|
{
|
||||||
|
return mat3(m[0][0], m[1][0], m[2][0],
|
||||||
|
m[0][1], m[1][1], m[2][1],
|
||||||
|
m[0][2], m[1][2], m[2][2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Send vertex attributes to fragment shader
|
||||||
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
fragTexCoord = vertexTexCoord;
|
||||||
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
|
|
||||||
|
// Calculate final vertex position
|
||||||
|
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||||
|
}
|
||||||
94
examples/shaders/resources/shaders/glsl100/fog.fs
Normal file
94
examples/shaders/resources/shaders/glsl100/fog.fs
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
#version 100
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
// Input vertex attributes (from vertex shader)
|
||||||
|
varying vec3 fragPosition;
|
||||||
|
varying vec2 fragTexCoord;
|
||||||
|
varying vec4 fragColor;
|
||||||
|
varying vec3 fragNormal;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
#define MAX_LIGHTS 4
|
||||||
|
#define LIGHT_DIRECTIONAL 0
|
||||||
|
#define LIGHT_POINT 1
|
||||||
|
|
||||||
|
struct MaterialProperty {
|
||||||
|
vec3 color;
|
||||||
|
int useSampler;
|
||||||
|
sampler2D sampler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
int enabled;
|
||||||
|
int type;
|
||||||
|
vec3 position;
|
||||||
|
vec3 target;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Input lighting values
|
||||||
|
uniform Light lights[MAX_LIGHTS];
|
||||||
|
uniform vec4 ambient;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
uniform float fogDensity;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Texel color fetching from texture sampler
|
||||||
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
vec3 lightDot = vec3(0.0);
|
||||||
|
vec3 normal = normalize(fragNormal);
|
||||||
|
vec3 viewD = normalize(viewPos - fragPosition);
|
||||||
|
vec3 specular = vec3(0.0);
|
||||||
|
|
||||||
|
// NOTE: Implement here your fragment shader code
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
{
|
||||||
|
if (lights[i].enabled == 1)
|
||||||
|
{
|
||||||
|
vec3 light = vec3(0.0);
|
||||||
|
|
||||||
|
if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position);
|
||||||
|
if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition);
|
||||||
|
|
||||||
|
float NdotL = max(dot(normal, light), 0.0);
|
||||||
|
lightDot += lights[i].color.rgb*NdotL;
|
||||||
|
|
||||||
|
float specCo = 0.0;
|
||||||
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0
|
||||||
|
specular += specCo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0)));
|
||||||
|
finalColor += texelColor*(ambient/10.0);
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
finalColor = pow(finalColor, vec4(1.0/2.2));
|
||||||
|
|
||||||
|
// Fog calculation
|
||||||
|
float dist = length(viewPos - fragPosition);
|
||||||
|
|
||||||
|
// these could be parameters...
|
||||||
|
const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
//const float fogDensity = 0.16;
|
||||||
|
|
||||||
|
// Exponential fog
|
||||||
|
float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity));
|
||||||
|
|
||||||
|
// Linear fog (less nice)
|
||||||
|
//const float fogStart = 2.0;
|
||||||
|
//const float fogEnd = 10.0;
|
||||||
|
//float fogFactor = (fogEnd - dist)/(fogEnd - fogStart);
|
||||||
|
|
||||||
|
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||||
|
|
||||||
|
gl_FragColor = mix(fogColor, finalColor, fogFactor);
|
||||||
|
}
|
||||||
81
examples/shaders/resources/shaders/glsl100/lighting.fs
Normal file
81
examples/shaders/resources/shaders/glsl100/lighting.fs
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#version 100
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
// Input vertex attributes (from vertex shader)
|
||||||
|
varying vec3 fragPosition;
|
||||||
|
varying vec2 fragTexCoord;
|
||||||
|
varying vec4 fragColor;
|
||||||
|
varying vec3 fragNormal;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
#define MAX_LIGHTS 4
|
||||||
|
#define LIGHT_DIRECTIONAL 0
|
||||||
|
#define LIGHT_POINT 1
|
||||||
|
|
||||||
|
struct MaterialProperty {
|
||||||
|
vec3 color;
|
||||||
|
int useSampler;
|
||||||
|
sampler2D sampler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
int enabled;
|
||||||
|
int type;
|
||||||
|
vec3 position;
|
||||||
|
vec3 target;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Input lighting values
|
||||||
|
uniform Light lights[MAX_LIGHTS];
|
||||||
|
uniform vec4 ambient;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Texel color fetching from texture sampler
|
||||||
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
vec3 lightDot = vec3(0.0);
|
||||||
|
vec3 normal = normalize(fragNormal);
|
||||||
|
vec3 viewD = normalize(viewPos - fragPosition);
|
||||||
|
vec3 specular = vec3(0.0);
|
||||||
|
|
||||||
|
// NOTE: Implement here your fragment shader code
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||||
|
{
|
||||||
|
if (lights[i].enabled == 1)
|
||||||
|
{
|
||||||
|
vec3 light = vec3(0.0);
|
||||||
|
|
||||||
|
if (lights[i].type == LIGHT_DIRECTIONAL)
|
||||||
|
{
|
||||||
|
light = -normalize(lights[i].target - lights[i].position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lights[i].type == LIGHT_POINT)
|
||||||
|
{
|
||||||
|
light = normalize(lights[i].position - fragPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
float NdotL = max(dot(normal, light), 0.0);
|
||||||
|
lightDot += lights[i].color.rgb*NdotL;
|
||||||
|
|
||||||
|
float specCo = 0.0;
|
||||||
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine
|
||||||
|
specular += specCo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0)));
|
||||||
|
finalColor += texelColor*(ambient/10.0);
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
gl_FragColor = pow(finalColor, vec4(1.0/2.2));
|
||||||
|
}
|
||||||
24
examples/shaders/resources/shaders/glsl100/mask.fs
Normal file
24
examples/shaders/resources/shaders/glsl100/mask.fs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#version 100
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
// Input vertex attributes (from vertex shader)
|
||||||
|
varying vec2 fragTexCoord;
|
||||||
|
varying vec4 fragColor;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform sampler2D mask;
|
||||||
|
uniform vec4 colDiffuse;
|
||||||
|
uniform int frame;
|
||||||
|
|
||||||
|
// NOTE: Add here your custom variables
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 maskColour = texture2D(mask, fragTexCoord + vec2(sin(-float(frame)/150.0)/10.0, cos(-float(frame)/170.0)/10.0));
|
||||||
|
if (maskColour.r < 0.25) discard;
|
||||||
|
vec4 texelColor = texture2D(texture0, fragTexCoord + vec2(sin(float(frame)/90.0)/8.0, cos(float(frame)/60.0)/8.0));
|
||||||
|
|
||||||
|
gl_FragColor = texelColor*maskColour;
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ out vec3 fragNormal;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Send vertex attributes to fragment shader
|
// Send vertex attributes to fragment shader
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
fragTexCoord = vertexTexCoord;
|
fragTexCoord = vertexTexCoord;
|
||||||
fragColor = vertexColor;
|
fragColor = vertexColor;
|
||||||
|
|
||||||
|
|
@ -55,25 +55,21 @@ void main()
|
||||||
if (lights[i].enabled == 1)
|
if (lights[i].enabled == 1)
|
||||||
{
|
{
|
||||||
vec3 light = vec3(0.0);
|
vec3 light = vec3(0.0);
|
||||||
if (lights[i].type == LIGHT_DIRECTIONAL) {
|
|
||||||
light = -normalize(lights[i].target - lights[i].position);
|
if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position);
|
||||||
}
|
if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition);
|
||||||
if (lights[i].type == LIGHT_POINT) {
|
|
||||||
light = normalize(lights[i].position - fragPosition);
|
|
||||||
}
|
|
||||||
float NdotL = max(dot(normal, light), 0.0);
|
float NdotL = max(dot(normal, light), 0.0);
|
||||||
lightDot += lights[i].color.rgb * NdotL;
|
lightDot += lights[i].color.rgb*NdotL;
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
if(NdotL > 0.0)
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0
|
||||||
specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16);//16 =shine
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finalColor = (texelColor * ((colDiffuse+vec4(specular,1)) * vec4(lightDot, 1.0)));
|
finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0)));
|
||||||
finalColor += texelColor * (ambient/10.0);
|
finalColor += texelColor*(ambient/10.0);
|
||||||
|
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
finalColor = pow(finalColor, vec4(1.0/2.2));
|
finalColor = pow(finalColor, vec4(1.0/2.2));
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#version 330
|
|
||||||
|
|
||||||
// Input vertex attributes
|
|
||||||
in vec3 vertexPosition;
|
|
||||||
in vec2 vertexTexCoord;
|
|
||||||
in vec3 vertexNormal;
|
|
||||||
in vec4 vertexColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform mat4 mvp;
|
|
||||||
uniform mat4 matModel;
|
|
||||||
|
|
||||||
// Output vertex attributes (to fragment shader)
|
|
||||||
out vec2 fragTexCoord;
|
|
||||||
out vec4 fragColor;
|
|
||||||
out vec3 fragPosition;
|
|
||||||
out vec3 fragNormal;
|
|
||||||
|
|
||||||
// NOTE: Add here your custom variables
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Send vertex attributes to fragment shader
|
|
||||||
fragTexCoord = vertexTexCoord;
|
|
||||||
fragColor = vertexColor;
|
|
||||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
|
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
|
||||||
|
|
||||||
// Calculate final vertex position
|
|
||||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
|
||||||
}
|
|
||||||
|
|
@ -69,7 +69,7 @@ void main()
|
||||||
lightDot += lights[i].color.rgb*NdotL;
|
lightDot += lights[i].color.rgb*NdotL;
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
// Input vertex attributes (from vertex shader)
|
||||||
in vec2 fragTexCoord;
|
in vec2 fragTexCoord;
|
||||||
|
in vec4 fragColor;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
uniform sampler2D texture0;
|
uniform sampler2D texture0;
|
||||||
|
|
@ -13,9 +14,9 @@ out vec4 finalColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 maskColour = texture(mask, fragTexCoord+vec2(sin(-frame/150.0)/10.0,cos(-frame/170.0)/10.0));
|
vec4 maskColour = texture(mask, fragTexCoord + vec2(sin(-frame/150.0)/10.0, cos(-frame/170.0)/10.0));
|
||||||
if (maskColour.r < 0.25) discard;
|
if (maskColour.r < 0.25) discard;
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord+vec2(sin(frame/90.0)/8.0,cos(frame/60.0)/8.0));
|
vec4 texelColor = texture(texture0, fragTexCoord + vec2(sin(frame/90.0)/8.0, cos(frame/60.0)/8.0));
|
||||||
|
|
||||||
finalColor = texelColor * maskColour;
|
finalColor = texelColor*maskColour;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#version 330
|
|
||||||
|
|
||||||
// Input vertex attributes
|
|
||||||
in vec3 vertexPosition;
|
|
||||||
in vec2 vertexTexCoord;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform mat4 mvp;
|
|
||||||
uniform mat4 matModel;
|
|
||||||
|
|
||||||
// Output vertex attributes (to fragment shader)
|
|
||||||
out vec2 fragTexCoord;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Send vertex attributes to fragment shader
|
|
||||||
fragTexCoord = vertexTexCoord;
|
|
||||||
|
|
||||||
// Calculate final vertex position
|
|
||||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
|
||||||
}
|
|
||||||
|
|
@ -68,17 +68,11 @@ typedef enum {
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
int lightsCount = 0; // Current amount of created lights
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader); // Create a light and get shader locations
|
Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader); // Create a light and get shader locations
|
||||||
void UpdateLightValues(Shader shader, Light light); // Send light properties to shader
|
void UpdateLightValues(Shader shader, Light light); // Send light properties to shader
|
||||||
//void InitLightLocations(Shader shader, Light *light); // Init light shader locations
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +104,7 @@ void UpdateLightValues(Shader shader, Light light); // Send light proper
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// ...
|
static int lightsCount = 0; // Current amount of created lights
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
|
|
@ -142,6 +136,8 @@ Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shade
|
||||||
char posName[32] = "lights[x].position\0";
|
char posName[32] = "lights[x].position\0";
|
||||||
char targetName[32] = "lights[x].target\0";
|
char targetName[32] = "lights[x].target\0";
|
||||||
char colorName[32] = "lights[x].color\0";
|
char colorName[32] = "lights[x].color\0";
|
||||||
|
|
||||||
|
// Set location name [x] depending on lights count
|
||||||
enabledName[7] = '0' + lightsCount;
|
enabledName[7] = '0' + lightsCount;
|
||||||
typeName[7] = '0' + lightsCount;
|
typeName[7] = '0' + lightsCount;
|
||||||
posName[7] = '0' + lightsCount;
|
posName[7] = '0' + lightsCount;
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ int main(void)
|
||||||
modelB.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
modelB.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
||||||
modelC.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
modelC.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
||||||
|
|
||||||
Shader shader = LoadShader("resources/shaders/glsl330/basic_lighting.vs",
|
Shader shader = LoadShader(FormatText("resources/shaders/glsl%i/base_lighting.vs", GLSL_VERSION),
|
||||||
"resources/shaders/glsl330/basic_lighting.fs");
|
FormatText("resources/shaders/glsl%i/lighting.fs", GLSL_VERSION));
|
||||||
|
|
||||||
// Get some shader loactions
|
// Get some shader loactions
|
||||||
shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
|
shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
|
||||||
|
|
@ -112,7 +112,7 @@ int main(void)
|
||||||
UpdateCamera(&camera); // Update camera
|
UpdateCamera(&camera); // Update camera
|
||||||
|
|
||||||
// Make the lights do differing orbits
|
// Make the lights do differing orbits
|
||||||
angle -= 0.02;
|
angle -= 0.02f;
|
||||||
lights[0].position.x = cosf(angle)*4.0f;
|
lights[0].position.x = cosf(angle)*4.0f;
|
||||||
lights[0].position.z = sinf(angle)*4.0f;
|
lights[0].position.z = sinf(angle)*4.0f;
|
||||||
lights[1].position.x = cosf(-angle*0.6f)*4.0f;
|
lights[1].position.x = cosf(-angle*0.6f)*4.0f;
|
||||||
|
|
@ -128,8 +128,8 @@ int main(void)
|
||||||
UpdateLightValues(shader, lights[3]);
|
UpdateLightValues(shader, lights[3]);
|
||||||
|
|
||||||
// Rotate the torus
|
// Rotate the torus
|
||||||
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025));
|
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025f));
|
||||||
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012));
|
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012f));
|
||||||
|
|
||||||
// Update the light shader with the camera view position
|
// Update the light shader with the camera view position
|
||||||
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
|
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
|
||||||
|
|
@ -161,7 +161,7 @@ int main(void)
|
||||||
|
|
||||||
DrawFPS(10, 10);
|
DrawFPS(10, 10);
|
||||||
|
|
||||||
DrawText("Keys RGB & W toggle lights", 10, 30, 20, DARKGRAY);
|
DrawText("Use keys RGBW to toggle lights", 10, 30, 20, DARKGRAY);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@
|
||||||
#define RLIGHTS_IMPLEMENTATION
|
#define RLIGHTS_IMPLEMENTATION
|
||||||
#include "rlights.h"
|
#include "rlights.h"
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP)
|
||||||
|
#define GLSL_VERSION 330
|
||||||
|
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
|
||||||
|
#define GLSL_VERSION 100
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
@ -61,7 +67,8 @@ int main(void)
|
||||||
modelC.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
modelC.materials[0].maps[MAP_DIFFUSE].texture = texture;
|
||||||
|
|
||||||
// Load shader and set up some uniforms
|
// Load shader and set up some uniforms
|
||||||
Shader shader = LoadShader("resources/shaders/glsl330/fog.vs", "resources/shaders/glsl330/fog.fs");
|
Shader shader = LoadShader(FormatText("resources/shaders/glsl%i/base_lighting.vs", GLSL_VERSION),
|
||||||
|
FormatText("resources/shaders/glsl%i/fog.fs", GLSL_VERSION));
|
||||||
shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
|
shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
|
||||||
shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
|
shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,12 @@
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "raymath.h"
|
#include "raymath.h"
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP)
|
||||||
|
#define GLSL_VERSION 330
|
||||||
|
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
|
||||||
|
#define GLSL_VERSION 100
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
@ -50,8 +56,8 @@ int main(void)
|
||||||
Model model3 = LoadModelFromMesh(sphere);
|
Model model3 = LoadModelFromMesh(sphere);
|
||||||
|
|
||||||
// Load the shader
|
// Load the shader
|
||||||
Shader shader = LoadShader("resources/shaders/glsl330/mask.vs", "resources/shaders/glsl330/mask.fs");
|
Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/mask.fs", GLSL_VERSION));
|
||||||
|
|
||||||
// Load and apply the diffuse texture (colour map)
|
// Load and apply the diffuse texture (colour map)
|
||||||
Texture texDiffuse = LoadTexture("resources/plasma.png");
|
Texture texDiffuse = LoadTexture("resources/plasma.png");
|
||||||
model1.materials[0].maps[MAP_DIFFUSE].texture = texDiffuse;
|
model1.materials[0].maps[MAP_DIFFUSE].texture = texDiffuse;
|
||||||
|
|
@ -66,7 +72,7 @@ int main(void)
|
||||||
shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(shader, "mask");
|
shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(shader, "mask");
|
||||||
|
|
||||||
// Frame is incremented each frame to animate the shader
|
// Frame is incremented each frame to animate the shader
|
||||||
int shaderFrame = GetShaderLocation(shader, "framesCounter");
|
int shaderFrame = GetShaderLocation(shader, "frame");
|
||||||
|
|
||||||
// Apply the shader to the two models
|
// Apply the shader to the two models
|
||||||
model1.materials[0].shader = shader;
|
model1.materials[0].shader = shader;
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ int main(void)
|
||||||
EndTextureMode();
|
EndTextureMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
|
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) || (GetGestureDetected() == GESTURE_DRAG))
|
||||||
{
|
{
|
||||||
// Paint circle into render texture
|
// Paint circle into render texture
|
||||||
// NOTE: To avoid discontinuous circles, we could store
|
// NOTE: To avoid discontinuous circles, we could store
|
||||||
|
|
@ -166,7 +166,7 @@ int main(void)
|
||||||
// Draw drawing circle for reference
|
// Draw drawing circle for reference
|
||||||
if (mousePos.y > 50)
|
if (mousePos.y > 50)
|
||||||
{
|
{
|
||||||
if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) DrawCircleLines(mousePos.x, mousePos.y, brushSize, colors[colorSelected]);
|
if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) DrawCircleLines(mousePos.x, mousePos.y, brushSize, GRAY);
|
||||||
else DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorSelected]);
|
else DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorSelected]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ int main(void)
|
||||||
DrawRectangle(0, 150, GetScreenWidth(), 80, BLACK);
|
DrawRectangle(0, 150, GetScreenWidth(), 80, BLACK);
|
||||||
DrawText("IMAGE SAVED: my_amazing_texture_painting.png", 150, 180, 20, RAYWHITE);
|
DrawText("IMAGE SAVED: my_amazing_texture_painting.png", 150, 180, 20, RAYWHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
||||||
145
src/core.c
145
src/core.c
|
|
@ -398,18 +398,18 @@ typedef struct CoreData {
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
bool cursorLockRequired; // Ask for cursor pointer lock on next click
|
bool cursorLockRequired; // Ask for cursor pointer lock on next click
|
||||||
#endif
|
#endif
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
|
|
||||||
char currentButtonState[3]; // Registers current mouse button state
|
char currentButtonState[3]; // Registers current mouse button state
|
||||||
char previousButtonState[3]; // Registers previous mouse button state
|
char previousButtonState[3]; // Registers previous mouse button state
|
||||||
int currentWheelMove; // Registers current mouse wheel variation
|
int currentWheelMove; // Registers current mouse wheel variation
|
||||||
int previousWheelMove; // Registers previous mouse wheel variation
|
int previousWheelMove; // Registers previous mouse wheel variation
|
||||||
#endif
|
|
||||||
#if defined(PLATFORM_RPI)
|
#if defined(PLATFORM_RPI)
|
||||||
char currentButtonStateEvdev[3]; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update)
|
char currentButtonStateEvdev[3]; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update)
|
||||||
#endif
|
#endif
|
||||||
} Mouse;
|
} Mouse;
|
||||||
struct {
|
struct {
|
||||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||||
|
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
||||||
|
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
int lastButtonPressed; // Register last gamepad button pressed
|
int lastButtonPressed; // Register last gamepad button pressed
|
||||||
|
|
@ -445,7 +445,7 @@ typedef struct CoreData {
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static CoreData CORE = { 0 }; // Global CORE context
|
static CoreData CORE = { 0 }; // Global CORE context
|
||||||
|
|
||||||
static char **dirFilesPath; // Store directory files paths as strings
|
static char **dirFilesPath = NULL; // Store directory files paths as strings
|
||||||
static int dirFilesCount = 0; // Count directory files strings
|
static int dirFilesCount = 0; // Count directory files strings
|
||||||
|
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
||||||
|
|
@ -477,8 +477,6 @@ static void SwapBuffers(void); // Copy back buffer to f
|
||||||
static void InitTimer(void); // Initialize timer
|
static void InitTimer(void); // Initialize timer
|
||||||
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
|
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
|
||||||
|
|
||||||
static bool GetKeyStatus(int key); // Returns if a key has been pressed
|
|
||||||
static bool GetMouseButtonStatus(int button); // Returns if a mouse button has been pressed
|
|
||||||
static int GetGamepadButton(int button); // Get gamepad button generic to all platforms
|
static int GetGamepadButton(int button); // Get gamepad button generic to all platforms
|
||||||
static int GetGamepadAxis(int axis); // Get gamepad axis generic to all platforms
|
static int GetGamepadAxis(int axis); // Get gamepad axis generic to all platforms
|
||||||
static void PollInputEvents(void); // Register user events
|
static void PollInputEvents(void); // Register user events
|
||||||
|
|
@ -1718,8 +1716,8 @@ Color ColorFromNormalized(Vector4 normalized)
|
||||||
// NOTE: Hue is returned as degrees [0..360]
|
// NOTE: Hue is returned as degrees [0..360]
|
||||||
Vector3 ColorToHSV(Color color)
|
Vector3 ColorToHSV(Color color)
|
||||||
{
|
{
|
||||||
|
Vector3 hsv = { 0 };
|
||||||
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
|
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
|
||||||
Vector3 hsv = { 0.0f, 0.0f, 0.0f };
|
|
||||||
float min, max, delta;
|
float min, max, delta;
|
||||||
|
|
||||||
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
||||||
|
|
@ -2306,7 +2304,7 @@ bool IsKeyPressed(int key)
|
||||||
{
|
{
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
if ((CORE.Input.Keyboard.currentKeyState[key] != CORE.Input.Keyboard.previousKeyState[key]) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
|
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
|
||||||
else pressed = false;
|
else pressed = false;
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
|
@ -2315,7 +2313,7 @@ bool IsKeyPressed(int key)
|
||||||
// Detect if a key is being pressed (key held down)
|
// Detect if a key is being pressed (key held down)
|
||||||
bool IsKeyDown(int key)
|
bool IsKeyDown(int key)
|
||||||
{
|
{
|
||||||
if (GetKeyStatus(key) == 1) return true;
|
if (CORE.Input.Keyboard.currentKeyState[key] == 1) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2324,7 +2322,7 @@ bool IsKeyReleased(int key)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
if ((CORE.Input.Keyboard.currentKeyState[key] != CORE.Input.Keyboard.previousKeyState[key]) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
|
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
|
||||||
else released = false;
|
else released = false;
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
|
|
@ -2333,7 +2331,7 @@ bool IsKeyReleased(int key)
|
||||||
// Detect if a key is NOT being pressed (key not held down)
|
// Detect if a key is NOT being pressed (key not held down)
|
||||||
bool IsKeyUp(int key)
|
bool IsKeyUp(int key)
|
||||||
{
|
{
|
||||||
if (GetKeyStatus(key) == 0) return true;
|
if (CORE.Input.Keyboard.currentKeyState[key] == 0) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2502,9 +2500,10 @@ bool IsMouseButtonPressed(int button)
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
if (IsGestureDetected(GESTURE_TAP)) pressed = true;
|
if (IsGestureDetected(GESTURE_TAP)) pressed = true;
|
||||||
#else
|
#else
|
||||||
// NOTE: On PLATFORM_DESKTOP and PLATFORM_WEB IsMouseButtonPressed() is equivalent to GESTURE_TAP
|
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) pressed = true;
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
|
|
||||||
(GetMouseButtonStatus(button) == 1)) pressed = true;
|
// Map touches to mouse buttons checking
|
||||||
|
if ((CORE.Input.Touch.currentTouchState[button] == 1) && (CORE.Input.Touch.previousTouchState[button] == 0)) pressed = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
|
@ -2518,9 +2517,10 @@ bool IsMouseButtonDown(int button)
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
if (IsGestureDetected(GESTURE_HOLD)) down = true;
|
if (IsGestureDetected(GESTURE_HOLD)) down = true;
|
||||||
#else
|
#else
|
||||||
// NOTE: On PLATFORM_DESKTOP and PLATFORM_WEB IsMouseButtonDown() is equivalent to GESTURE_HOLD or GESTURE_DRAG
|
if (CORE.Input.Mouse.currentButtonState[button] == 1) down = true;
|
||||||
if (GetMouseButtonStatus(button) == 1) down = true;
|
|
||||||
// || IsGestureDetected(GESTURE_HOLD) || IsGestureDetected(GESTURE_DRAG)) down = true;
|
// Map touches to mouse buttons checking
|
||||||
|
if (CORE.Input.Touch.currentTouchState[button] == 1) down = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return down;
|
return down;
|
||||||
|
|
@ -2532,12 +2532,14 @@ bool IsMouseButtonReleased(int button)
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
# if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
released = GetGestureDetected() == GESTURE_TAP;
|
released = GetGestureDetected() == GESTURE_TAP;
|
||||||
# endif
|
#endif
|
||||||
#else
|
#else
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
|
if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) released = true;
|
||||||
(GetMouseButtonStatus(button) == 0)) released = true;
|
|
||||||
|
// Map touches to mouse buttons checking
|
||||||
|
if ((CORE.Input.Touch.currentTouchState[button] == 0) && (CORE.Input.Touch.previousTouchState[button] == 1)) released = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
|
|
@ -2549,7 +2551,10 @@ bool IsMouseButtonUp(int button)
|
||||||
bool up = false;
|
bool up = false;
|
||||||
|
|
||||||
#if !defined(PLATFORM_ANDROID)
|
#if !defined(PLATFORM_ANDROID)
|
||||||
if (GetMouseButtonStatus(button) == 0) up = true;
|
if (CORE.Input.Mouse.currentButtonState[button] == 0) up = true;
|
||||||
|
|
||||||
|
// Map touches to mouse buttons checking
|
||||||
|
if (CORE.Input.Touch.currentTouchState[button] == 0) up = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return up;
|
return up;
|
||||||
|
|
@ -2578,12 +2583,13 @@ int GetMouseY(void)
|
||||||
// Returns mouse position XY
|
// Returns mouse position XY
|
||||||
Vector2 GetMousePosition(void)
|
Vector2 GetMousePosition(void)
|
||||||
{
|
{
|
||||||
Vector2 position = { 0.0f, 0.0f };
|
Vector2 position = { 0 };
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
|
||||||
position = GetTouchPosition(0);
|
position = GetTouchPosition(0);
|
||||||
#else
|
#else
|
||||||
position = (Vector2){ (CORE.Input.Mouse.position.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x, (CORE.Input.Mouse.position.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y };
|
position.x = (CORE.Input.Mouse.position.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
||||||
|
position.y = (CORE.Input.Mouse.position.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
|
|
@ -2682,7 +2688,6 @@ Vector2 GetTouchPosition(int index)
|
||||||
// TODO: GLFW is not supporting multi-touch input just yet
|
// TODO: GLFW is not supporting multi-touch input just yet
|
||||||
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
||||||
|
|
||||||
if (index == 0) position = GetMousePosition();
|
if (index == 0) position = GetMousePosition();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -3452,36 +3457,6 @@ static void Wait(float ms)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get one key state
|
|
||||||
static bool GetKeyStatus(int key)
|
|
||||||
{
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
return glfwGetKey(CORE.Window.handle, key);
|
|
||||||
#elif defined(PLATFORM_ANDROID)
|
|
||||||
// NOTE: Android supports up to 260 keys
|
|
||||||
if (key < 0 || key > 260) return false;
|
|
||||||
else return CORE.Input.Keyboard.currentKeyState[key];
|
|
||||||
#elif defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
|
||||||
// NOTE: Keys states are filled in PollInputEvents()
|
|
||||||
if (key < 0 || key > 511) return false;
|
|
||||||
else return CORE.Input.Keyboard.currentKeyState[key];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get one mouse button state
|
|
||||||
static bool GetMouseButtonStatus(int button)
|
|
||||||
{
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
return glfwGetMouseButton(CORE.Window.handle, button);
|
|
||||||
#elif defined(PLATFORM_ANDROID)
|
|
||||||
// TODO: Check for virtual mouse?
|
|
||||||
return false;
|
|
||||||
#elif defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
|
||||||
// NOTE: Mouse buttons states are filled in PollInputEvents()
|
|
||||||
return CORE.Input.Mouse.currentButtonState[button];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gamepad button generic to all platforms
|
// Get gamepad button generic to all platforms
|
||||||
static int GetGamepadButton(int button)
|
static int GetGamepadButton(int button)
|
||||||
{
|
{
|
||||||
|
|
@ -3595,7 +3570,7 @@ static void PollInputEvents(void)
|
||||||
|
|
||||||
#if defined(PLATFORM_RPI)
|
#if defined(PLATFORM_RPI)
|
||||||
// Register previous keys states
|
// Register previous keys states
|
||||||
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)
|
||||||
|
|
@ -3631,6 +3606,7 @@ static void PollInputEvents(void)
|
||||||
// Register previous mouse states
|
// Register previous mouse states
|
||||||
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
||||||
CORE.Input.Mouse.currentWheelMove = 0;
|
CORE.Input.Mouse.currentWheelMove = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
||||||
|
|
||||||
// Loop over pending messages
|
// Loop over pending messages
|
||||||
|
|
@ -3771,16 +3747,7 @@ static void PollInputEvents(void)
|
||||||
#endif // PLATFORM_UWP
|
#endif // PLATFORM_UWP
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
// Mouse input polling
|
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
|
||||||
double mouseX;
|
|
||||||
double mouseY;
|
|
||||||
|
|
||||||
glfwGetCursorPos(CORE.Window.handle, &mouseX, &mouseY);
|
|
||||||
|
|
||||||
CORE.Input.Mouse.position.x = (float)mouseX;
|
|
||||||
CORE.Input.Mouse.position.y = (float)mouseY;
|
|
||||||
|
|
||||||
// Keyboard input polling (automatically managed by GLFW3 through callback)
|
|
||||||
|
|
||||||
// Register previous keys states
|
// Register previous keys states
|
||||||
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];
|
||||||
|
|
@ -3788,8 +3755,12 @@ static void PollInputEvents(void)
|
||||||
// Register previous mouse states
|
// Register previous mouse states
|
||||||
for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
||||||
|
|
||||||
|
// Register previous mouse wheel state
|
||||||
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
||||||
CORE.Input.Mouse.currentWheelMove = 0;
|
CORE.Input.Mouse.currentWheelMove = 0;
|
||||||
|
|
||||||
|
// Register previous touch states
|
||||||
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP)
|
||||||
|
|
@ -4015,23 +3986,30 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_SCREEN_CAPTURE
|
#endif // SUPPORT_SCREEN_CAPTURE
|
||||||
}
|
}
|
||||||
else CORE.Input.Keyboard.currentKeyState[key] = action;
|
else
|
||||||
|
{
|
||||||
|
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
||||||
|
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
||||||
|
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
||||||
|
else CORE.Input.Keyboard.currentKeyState[key] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Mouse Button Callback, runs on mouse button pressed
|
// GLFW3 Mouse Button Callback, runs on mouse button pressed
|
||||||
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
|
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.previousButtonState[button] = CORE.Input.Mouse.currentButtonState[button];
|
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
|
||||||
|
// but future releases may add more actions (i.e. GLFW_REPEAT)
|
||||||
CORE.Input.Mouse.currentButtonState[button] = action;
|
CORE.Input.Mouse.currentButtonState[button] = action;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
||||||
// Process mouse events as touches to be able to use mouse-gestures
|
// Process mouse events as touches to be able to use mouse-gestures
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
// Register touch actions
|
// Register touch actions
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN;
|
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) gestureEvent.touchAction = TOUCH_DOWN;
|
||||||
else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP;
|
else if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) gestureEvent.touchAction = TOUCH_UP;
|
||||||
|
|
||||||
// NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback()
|
// NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback()
|
||||||
|
|
||||||
// Assign a pointer ID
|
// Assign a pointer ID
|
||||||
|
|
@ -4055,6 +4033,10 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
|
||||||
// GLFW3 Cursor Position Callback, runs on mouse move
|
// GLFW3 Cursor Position Callback, runs on mouse move
|
||||||
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
||||||
{
|
{
|
||||||
|
CORE.Input.Mouse.position.x = (float)x;
|
||||||
|
CORE.Input.Mouse.position.y = (float)y;
|
||||||
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.position;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
||||||
// Process mouse events as touches to be able to use mouse-gestures
|
// Process mouse events as touches to be able to use mouse-gestures
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
@ -4068,9 +4050,7 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
||||||
gestureEvent.pointCount = 1;
|
gestureEvent.pointCount = 1;
|
||||||
|
|
||||||
// Register touch points position, only one point registered
|
// Register touch points position, only one point registered
|
||||||
gestureEvent.position[0] = (Vector2){ (float)x, (float)y };
|
gestureEvent.position[0] = CORE.Input.Touch.position[0];
|
||||||
|
|
||||||
CORE.Input.Touch.position[0] = gestureEvent.position[0];
|
|
||||||
|
|
||||||
// Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
|
// Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
|
||||||
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
||||||
|
|
@ -4274,7 +4254,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *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)
|
||||||
{
|
{
|
||||||
CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
|
CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
|
||||||
|
|
||||||
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
|
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
|
||||||
CORE.Input.Keyboard.keyPressedQueueCount++;
|
CORE.Input.Keyboard.keyPressedQueueCount++;
|
||||||
|
|
@ -4388,8 +4368,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
CORE.Input.Touch.position[0].x = 0;
|
CORE.Input.Touch.position[0].x = 0;
|
||||||
CORE.Input.Touch.position[0].y = 0;
|
CORE.Input.Touch.position[0].y = 0;
|
||||||
}
|
}
|
||||||
else // TODO:Not sure what else should be handled
|
else return 0; // 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 };
|
||||||
|
|
@ -4496,6 +4475,12 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
|
||||||
// Register touch input events
|
// Register touch input events
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < touchEvent->numTouches; i++)
|
||||||
|
{
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) CORE.Input.Touch.currentTouchState[i] = 1;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
|
|
@ -4638,7 +4623,7 @@ static void ProcessKeyboard(void)
|
||||||
|
|
||||||
// Reset pressed keys array (it will be filled below)
|
// Reset pressed keys array (it will be filled below)
|
||||||
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;
|
||||||
|
|
||||||
// Check keys from event input workers (This is the new keyboard reading method)
|
// Check keys from event input workers (This is the new keyboard reading method)
|
||||||
//for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = CORE.Input.Keyboard.currentKeyStateEvdev[i];
|
//for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = CORE.Input.Keyboard.currentKeyStateEvdev[i];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@
|
||||||
#define FormatText TextFormat
|
#define FormatText TextFormat
|
||||||
#define SubText TextSubtext
|
#define SubText TextSubtext
|
||||||
#define ShowWindow UnhideWindow
|
#define ShowWindow UnhideWindow
|
||||||
|
#define LoadText LoadFileText
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Structures Definition
|
// Structures Definition
|
||||||
|
|
@ -951,6 +952,8 @@ RLAPI int GetRandomValue(int min, int max); // Returns a r
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, int *bytesRead); // Load file data as byte array (read)
|
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 void SaveFileData(const char *fileName, void *data, int bytesToWrite); // Save data to file from byte array (write)
|
||||||
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
|
RLAPI void SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
||||||
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
|
||||||
|
|
@ -1322,9 +1325,8 @@ RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight);
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Shader loading/unloading functions
|
// Shader loading/unloading functions
|
||||||
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
|
||||||
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
||||||
RLAPI Shader LoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
|
RLAPI Shader LoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
|
||||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
RLAPI Shader GetShaderDefault(void); // Get default shader
|
RLAPI Shader GetShaderDefault(void); // Get default shader
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,14 @@ RMDEF Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rotate Vector by float in Degrees.
|
||||||
|
RMDEF Vector2 Vector2Rotate(Vector2 v, float degs)
|
||||||
|
{
|
||||||
|
float rads = degs*DEG2RAD;
|
||||||
|
Vector2 result = {v.x * cosf(rads) - v.y * sinf(rads) , v.x * sinf(rads) + v.y * cosf(rads) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Vector3 math
|
// Module Functions Definition - Vector3 math
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
105
src/rlgl.h
105
src/rlgl.h
|
|
@ -546,9 +546,8 @@ RLAPI void rlUnloadMesh(Mesh mesh); // Unl
|
||||||
// NOTE: This functions are useless when using OpenGL 1.1
|
// NOTE: This functions are useless when using OpenGL 1.1
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Shader loading/unloading functions
|
// Shader loading/unloading functions
|
||||||
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
|
||||||
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
||||||
RLAPI Shader LoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
|
RLAPI Shader LoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
|
||||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
RLAPI Shader GetShaderDefault(void); // Get default shader
|
RLAPI Shader GetShaderDefault(void); // Get default shader
|
||||||
|
|
@ -588,6 +587,7 @@ 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 char *LoadFileText(const char *fileName); // Load chars array from text file
|
||||||
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
|
||||||
|
|
||||||
|
|
@ -605,22 +605,20 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data
|
||||||
|
|
||||||
#if defined(RLGL_IMPLEMENTATION)
|
#if defined(RLGL_IMPLEMENTATION)
|
||||||
|
|
||||||
#if !defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
|
#include <stdio.h> // Required for: fopen(), fseek(), fread(), fclose() [LoadFileText]
|
||||||
|
#else
|
||||||
// Check if config flags have been externally provided on compilation line
|
// Check if config flags have been externally provided on compilation line
|
||||||
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
#endif
|
#endif
|
||||||
|
#include "raymath.h" // Required for: Vector3 and Matrix functions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
#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(), fabs()
|
#include <math.h> // Required for: atan2f(), fabs()
|
||||||
|
|
||||||
#if !defined(RLGL_STANDALONE)
|
|
||||||
#include "raymath.h" // Required for: Vector3 and Matrix functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
||||||
|
|
@ -2984,49 +2982,6 @@ Shader GetShaderDefault(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load text data from file
|
|
||||||
// NOTE: text chars array should be freed manually
|
|
||||||
char *LoadText(const char *fileName)
|
|
||||||
{
|
|
||||||
char *text = NULL;
|
|
||||||
|
|
||||||
if (fileName != NULL)
|
|
||||||
{
|
|
||||||
FILE *textFile = fopen(fileName, "rt");
|
|
||||||
|
|
||||||
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);
|
|
||||||
int size = ftell(textFile);
|
|
||||||
fseek(textFile, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
text = (char *)RL_MALLOC(sizeof(char)*(size + 1));
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(textFile);
|
|
||||||
}
|
|
||||||
else TRACELOG(LOG_WARNING, "[%s] Text file could not be opened", fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load shader from files and bind default locations
|
// Load shader from files and bind default locations
|
||||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||||
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
|
|
@ -3038,8 +2993,8 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
char *vShaderStr = NULL;
|
char *vShaderStr = NULL;
|
||||||
char *fShaderStr = NULL;
|
char *fShaderStr = NULL;
|
||||||
|
|
||||||
if (vsFileName != NULL) vShaderStr = LoadText(vsFileName);
|
if (vsFileName != NULL) vShaderStr = LoadFileText(vsFileName);
|
||||||
if (fsFileName != NULL) fShaderStr = LoadText(fsFileName);
|
if (fsFileName != NULL) fShaderStr = LoadFileText(fsFileName);
|
||||||
|
|
||||||
shader = LoadShaderCode(vShaderStr, fShaderStr);
|
shader = LoadShaderCode(vShaderStr, fShaderStr);
|
||||||
|
|
||||||
|
|
@ -4643,6 +4598,50 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
|
// Load text data from file, returns a '\0' terminated string
|
||||||
|
// NOTE: text chars array should be freed manually
|
||||||
|
char *LoadFileText(const char *fileName)
|
||||||
|
{
|
||||||
|
char *text = NULL;
|
||||||
|
|
||||||
|
if (fileName != NULL)
|
||||||
|
{
|
||||||
|
FILE *textFile = fopen(fileName, "rt");
|
||||||
|
|
||||||
|
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);
|
||||||
|
int size = ftell(textFile);
|
||||||
|
fseek(textFile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
text = (char *)RL_MALLOC(sizeof(char)*(size + 1));
|
||||||
|
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';
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "[%s] Text file loaded successfully", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] Text file could not be read", fileName);
|
||||||
|
|
||||||
|
fclose(textFile);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] Text file could not be opened", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "File name provided is not valid");
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
|
|
||||||
|
|
@ -173,8 +173,8 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
|
||||||
<div class="emscripten" id="status">Downloading...</div>
|
<div class="emscripten" id="status">Downloading...</div>
|
||||||
|
|
||||||
<span id='controls'>
|
<span id='controls'>
|
||||||
<span><input type="button" value="🖵 FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
|
<span><input type="button" value="FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
|
||||||
<span><input type="button" id="btn-audio" value="🔇 SUSPEND" onclick="toggleAudio()"></span>
|
<span><input type="button" id="btn-audio" value="AUDIO OFF" onclick="toggleAudio()"></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="emscripten">
|
<div class="emscripten">
|
||||||
|
|
@ -305,7 +305,7 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
|
||||||
construct(target, args) {
|
construct(target, args) {
|
||||||
const result = new target(...args);
|
const result = new target(...args);
|
||||||
audioContexList.push(result);
|
audioContexList.push(result);
|
||||||
if (result.state == "suspended") audioBtn.value = "🔈 RESUME";
|
if (result.state == "suspended") audioBtn.value = "AUDIO ON";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -318,8 +318,8 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
|
||||||
else if (ctx.state == "running") ctx.suspend();
|
else if (ctx.state == "running") ctx.suspend();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (resumed) audioBtn.value = "🔇 SUSPEND";
|
if (resumed) audioBtn.value = "AUDIO OFF";
|
||||||
else audioBtn.value = "🔈 RESUME";
|
else audioBtn.value = "AUDIO ON";
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{{{ SCRIPT }}}
|
{{{ SCRIPT }}}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
|
||||||
// Required for: rlLoadTexture() rlDeleteTextures(),
|
// Required for: rlLoadTexture() rlDeleteTextures(),
|
||||||
// rlGenerateMipmaps(), some funcs for DrawTexturePro()
|
// rlGenerateMipmaps(), some funcs for DrawTexturePro()
|
||||||
|
|
||||||
// Support only desired texture formats on stb_image
|
// Support only desired texture formats on stb_image
|
||||||
#if !defined(SUPPORT_FILEFORMAT_BMP)
|
#if !defined(SUPPORT_FILEFORMAT_BMP)
|
||||||
|
|
|
||||||
128
src/utils.c
128
src/utils.c
|
|
@ -169,32 +169,36 @@ unsigned char *LoadFileData(const char *fileName, int *bytesRead)
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
*bytesRead = 0;
|
*bytesRead = 0;
|
||||||
|
|
||||||
FILE *file = fopen(fileName, "rb");
|
if (fileName != NULL)
|
||||||
|
|
||||||
if (file != NULL)
|
|
||||||
{
|
{
|
||||||
// WARNING: On binary streams SEEK_END could not be found,
|
FILE *file = fopen(fileName, "rb");
|
||||||
// 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)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
data = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*size);
|
// 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);
|
||||||
|
|
||||||
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
if (size > 0)
|
||||||
int count = fread(data, sizeof(unsigned char), size, file);
|
{
|
||||||
*bytesRead = count;
|
data = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*size);
|
||||||
|
|
||||||
if (count != size) TRACELOG(LOG_WARNING, "[%s] File partially loaded", fileName);
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
else TRACELOG(LOG_INFO, "[%s] File loaded successfully", fileName);
|
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 read", fileName);
|
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
else TRACELOG(LOG_WARNING, "File name provided is not valid");
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
@ -202,18 +206,88 @@ unsigned char *LoadFileData(const char *fileName, int *bytesRead)
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
void SaveFileData(const char *fileName, void *data, int bytesToWrite)
|
void SaveFileData(const char *fileName, void *data, int bytesToWrite)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(fileName, "wb");
|
if (fileName != NULL)
|
||||||
|
|
||||||
if (file != NULL)
|
|
||||||
{
|
{
|
||||||
int count = fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
||||||
if (count == 0) TRACELOG(LOG_WARNING, "[%s] File could not be written", fileName);
|
if (file != NULL)
|
||||||
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "[%s] File partially written", fileName);
|
{
|
||||||
|
int count = fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
||||||
|
|
||||||
fclose(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);
|
||||||
|
else TRACELOG(LOG_INFO, "[%s] File successfully saved", fileName);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "[%s] File could not be opened", fileName);
|
else TRACELOG(LOG_WARNING, "File name provided is not valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load text data from file, returns a '\0' terminated string
|
||||||
|
// NOTE: text chars array should be freed manually
|
||||||
|
char *LoadFileText(const char *fileName)
|
||||||
|
{
|
||||||
|
char *text = NULL;
|
||||||
|
|
||||||
|
if (fileName != NULL)
|
||||||
|
{
|
||||||
|
FILE *textFile = fopen(fileName, "rt");
|
||||||
|
|
||||||
|
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);
|
||||||
|
int size = ftell(textFile);
|
||||||
|
fseek(textFile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
text = (char *)RL_MALLOC(sizeof(char)*(size + 1));
|
||||||
|
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';
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "[%s] Text file loaded successfully", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] Text file could not be read", fileName);
|
||||||
|
|
||||||
|
fclose(textFile);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] Text file could not be opened", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "File name provided is not valid");
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save text data to file (write), string must be '\0' terminated
|
||||||
|
void SaveFileText(const char *fileName, char *text)
|
||||||
|
{
|
||||||
|
if (fileName != NULL)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(fileName, "wt");
|
||||||
|
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
int count = fprintf(file, "%s", text);
|
||||||
|
|
||||||
|
if (count == 0) TRACELOG(LOG_WARNING, "[%s] Text file could not be written", fileName);
|
||||||
|
else TRACELOG(LOG_INFO, "[%s] Text file successfully saved", fileName);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "[%s] Text file could not be opened", fileName);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "File name provided is not valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user