-
+
diff --git a/data/gui/user_screen.stkgui b/data/gui/user_screen.stkgui
index 1e8b79a69..ce64e1a94 100644
--- a/data/gui/user_screen.stkgui
+++ b/data/gui/user_screen.stkgui
@@ -15,42 +15,32 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -66,9 +56,7 @@
I18N="Login dialog" text="Add user" label_location="bottom"/>
-
-
diff --git a/data/gui/user_screen_tab.stkgui b/data/gui/user_screen_tab.stkgui
index 2600ad844..4ebb48810 100644
--- a/data/gui/user_screen_tab.stkgui
+++ b/data/gui/user_screen_tab.stkgui
@@ -16,30 +16,22 @@
+
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
@@ -65,6 +57,7 @@
+
diff --git a/data/shaders/bloom.frag b/data/shaders/bloom.frag
index 8861a29db..099922bab 100644
--- a/data/shaders/bloom.frag
+++ b/data/shaders/bloom.frag
@@ -14,5 +14,5 @@ void main()
Yxy.x = smoothstep(WhiteYxy.x, WhiteYxy.x * 4, Yxy.x);
- FragColor = vec4(getRGBFromCIEXxy(Yxy), 1.0);
+ FragColor = vec4(max(vec3(0.), getRGBFromCIEXxy(Yxy)), 1.0);
}
diff --git a/data/shaders/detailledobject_pass2.frag b/data/shaders/detailledobject_pass2.frag
index a426b6935..5b19966cc 100644
--- a/data/shaders/detailledobject_pass2.frag
+++ b/data/shaders/detailledobject_pass2.frag
@@ -1,9 +1,11 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D Detail;
+layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D Detail;
+uniform sampler2D SpecMap;
#endif
#if __VERSION__ >= 130
@@ -16,7 +18,7 @@ varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@@ -28,6 +30,6 @@ void main(void)
#endif
vec4 detail = texture(Detail, uv_bis);
color *= detail;
- vec3 LightFactor = getLightFactor(1. - color.a);
- FragColor = vec4(color.xyz * LightFactor, 1.);
+ float specmap = texture(SpecMap, uv).g;
+ FragColor = vec4(getLightFactor(color.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/diffuseenvmap.frag b/data/shaders/diffuseenvmap.frag
index c88478b23..2ded6b2b0 100644
--- a/data/shaders/diffuseenvmap.frag
+++ b/data/shaders/diffuseenvmap.frag
@@ -2,11 +2,15 @@ uniform float blueLmn[9];
uniform float greenLmn[9];
uniform float redLmn[9];
uniform sampler2D ntex;
+uniform sampler2D dtex;
+uniform samplerCube tex;
uniform mat4 TransposeViewMatrix;
out vec4 Diff;
+out vec4 Spec;
vec3 DecodeNormal(vec2 n);
+vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
mat4 getMatrix(float L[9])
{
@@ -24,8 +28,9 @@ void main(void)
{
vec2 uv = gl_FragCoord.xy / screen;
vec3 normal = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
+
// Convert normal in world space (where SH coordinates were computed)
- vec4 extendednormal = TransposeViewMatrix * vec4(normal, 1.);
+ vec4 extendednormal = TransposeViewMatrix * vec4(normal, 0.);
extendednormal.w = 1.;
mat4 rmat = getMatrix(redLmn);
mat4 gmat = getMatrix(greenLmn);
@@ -36,4 +41,16 @@ void main(void)
float b = dot(extendednormal, bmat * extendednormal);
Diff = max(0.25 * vec4(r, g, b, .1), vec4(0.));
+
+ float z = texture(dtex, uv).x;
+
+ vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
+ vec3 eyedir = -normalize(xpos.xyz);
+ vec3 sampleDirection = reflect(-eyedir, normal);
+ sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
+
+ float specval = texture(ntex, uv).z;
+ float lodval = 16 * (1. - ((log2(specval) - 1.) / 10.));
+ vec4 specular = textureLod(tex, sampleDirection, lodval);
+ Spec = max(specular, vec4(0.));
}
diff --git a/data/shaders/grass_pass2.frag b/data/shaders/grass_pass2.frag
index 408e78365..6b677ceea 100644
--- a/data/shaders/grass_pass2.frag
+++ b/data/shaders/grass_pass2.frag
@@ -1,9 +1,11 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D dtex;
+layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D dtex;
+uniform sampler2D SpecMap;
#endif
uniform vec3 SunDir;
@@ -12,10 +14,18 @@ in vec3 nor;
in vec2 uv;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
+ vec4 color = texture(Albedo, uv);
+#ifdef GL_ARB_bindless_texture
+#ifdef SRGBBindlessFix
+ color.xyz = pow(color.xyz, vec3(2.2));
+#endif
+#endif
+ if (color.a < 0.5) discard;
+
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
@@ -30,14 +40,8 @@ void main(void)
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
+ float specmap = texture(SpecMap, uv).g;
- vec4 color = texture(Albedo, uv);
-#ifdef GL_ARB_bindless_texture
-#ifdef SRGBBindlessFix
- color.xyz = pow(color.xyz, vec3(2.2));
-#endif
-#endif
- if (color.a < 0.5) discard;
- vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
+ vec3 LightFactor = color.xyz * (scattering * 0.3) + getLightFactor(color.xyz, vec3(1.), specmap);
FragColor = vec4(color.xyz * LightFactor, 1.);
}
diff --git a/data/shaders/instanced_detailledobject_pass2.frag b/data/shaders/instanced_detailledobject_pass2.frag
index c631fe3ef..927a6a845 100644
--- a/data/shaders/instanced_detailledobject_pass2.frag
+++ b/data/shaders/instanced_detailledobject_pass2.frag
@@ -1,22 +1,25 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
uniform sampler2D Detail;
+uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
+flat in sampler2D secondhandle;
flat in sampler2D thirdhandle;
#endif
in vec2 uv;
in vec2 uv_bis;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 color = texture(handle, uv);
+ float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
@@ -24,8 +27,8 @@ void main(void)
#else
vec4 color = texture(Albedo, uv);
vec4 detail = texture(Detail, uv_bis);
+ float specmap = texture(SpecMap, uv).g;
#endif
color *= detail;
- vec3 LightFactor = getLightFactor(1. - color.a);
- FragColor = vec4(color.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(color.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/instanced_grass.vert b/data/shaders/instanced_grass.vert
index 5a9d11769..5ca0a66a3 100644
--- a/data/shaders/instanced_grass.vert
+++ b/data/shaders/instanced_grass.vert
@@ -11,6 +11,7 @@ layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
+layout(location = 11) in sampler2D SecondHandle;
#endif
#else
@@ -28,6 +29,7 @@ out vec3 nor;
out vec2 uv;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
+flat out sampler2D secondhandle;
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@@ -42,5 +44,6 @@ void main()
uv = Texcoord;
#ifdef GL_ARB_bindless_texture
handle = Handle;
+ secondhandle = SecondHandle;
#endif
}
diff --git a/data/shaders/instanced_grass_pass2.frag b/data/shaders/instanced_grass_pass2.frag
index b297a4c88..0bd7f0dbe 100644
--- a/data/shaders/instanced_grass_pass2.frag
+++ b/data/shaders/instanced_grass_pass2.frag
@@ -2,6 +2,7 @@
layout(bindless_sampler) uniform sampler2D dtex;
#else
uniform sampler2D Albedo;
+uniform sampler2D SpecMap;
uniform sampler2D dtex;
#endif
@@ -9,15 +10,28 @@ uniform vec3 SunDir;
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
+flat in sampler2D secondhandle;
#endif
in vec3 nor;
in vec2 uv;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
+#ifdef GL_ARB_bindless_texture
+ vec4 color = texture(handle, uv);
+ float specmap = texture(secondhandle, uv).g;
+#ifdef SRGBBindlessFix
+ color.xyz = pow(color.xyz, vec3(2.2));
+#endif
+#else
+ vec4 color = texture(Albedo, uv);
+ float specmap = texture(SpecMap, uv).g;
+#endif
+ if (color.a < 0.5) discard;
+
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
@@ -33,15 +47,7 @@ void main(void)
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
-#ifdef GL_ARB_bindless_texture
- vec4 color = texture(handle, uv);
-#ifdef SRGBBindlessFix
- color.xyz = pow(color.xyz, vec3(2.2));
-#endif
-#else
- vec4 color = texture(Albedo, uv);
-#endif
- if (color.a < 0.5) discard;
- vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
- FragColor = vec4(color.xyz * LightFactor, 1.);
+
+ vec3 LightFactor = color.xyz * (scattering * 0.3) + getLightFactor(color.xyz, vec3(1.), specmap);
+ FragColor = vec4(LightFactor, 1.);
}
diff --git a/data/shaders/instanced_object_pass2.frag b/data/shaders/instanced_object_pass2.frag
index 76176ba37..c260d7aab 100644
--- a/data/shaders/instanced_object_pass2.frag
+++ b/data/shaders/instanced_object_pass2.frag
@@ -1,27 +1,30 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
+uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
+flat in sampler2D secondhandle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
+ float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
col.xyz = pow(col.xyz, vec3(2.2));
#endif
#else
vec4 col = texture(Albedo, uv);
+ float specmap = texture(SpecMap, uv).g;
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(col.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/instanced_objectpass_spheremap.frag b/data/shaders/instanced_objectpass_spheremap.frag
index 5365dd7ef..21414ee31 100644
--- a/data/shaders/instanced_objectpass_spheremap.frag
+++ b/data/shaders/instanced_objectpass_spheremap.frag
@@ -12,7 +12,7 @@ out vec4 FragColor;
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
vec3 texc = gl_FragCoord.xyz / vec3(screen, 1.);
@@ -29,7 +29,6 @@ void main() {
#else
vec4 detail0 = texture(tex, r.xy / m + .5);
#endif
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(detail0.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(detail0.xyz, vec3(1.), 0.), 1.);
}
diff --git a/data/shaders/instanced_objectref_pass2.frag b/data/shaders/instanced_objectref_pass2.frag
index 201f610a1..41f3dc34f 100644
--- a/data/shaders/instanced_objectref_pass2.frag
+++ b/data/shaders/instanced_objectref_pass2.frag
@@ -1,28 +1,31 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
+uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
+flat in sampler2D secondhandle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
+ float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
col.xyz = pow(col.xyz, vec3(2.2));
#endif
#else
vec4 col = texture(Albedo, uv);
+ float specmap = texture(SpecMap, uv).g;
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
if (col.a * color.a < 0.5) discard;
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(col.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/object_pass2.frag b/data/shaders/object_pass2.frag
index 047f0a192..ba984f87d 100644
--- a/data/shaders/object_pass2.frag
+++ b/data/shaders/object_pass2.frag
@@ -1,14 +1,16 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
+layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
+uniform sampler2D SpecMap;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@@ -21,6 +23,6 @@ void main(void)
vec4 col = texture(Albedo, uv);
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(col.xyz * LightFactor, 1.);
+ float specmap = texture(SpecMap, uv).g;
+ FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/objectpass_spheremap.frag b/data/shaders/objectpass_spheremap.frag
index 8e4e0f4fc..e5ed033d1 100644
--- a/data/shaders/objectpass_spheremap.frag
+++ b/data/shaders/objectpass_spheremap.frag
@@ -15,7 +15,7 @@ varying vec3 nor;
#endif
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
vec3 texc = gl_FragCoord.xyz / vec3(screen, 1.);
@@ -30,7 +30,6 @@ void main() {
detail0.xyz = pow(detail0.xyz, vec3(2.2));
#endif
#endif
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(detail0.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(detail0.xyz, vec3(1.), 0.), 1.);
}
diff --git a/data/shaders/objectref_pass2.frag b/data/shaders/objectref_pass2.frag
index 13ff676f8..a7fd08dca 100644
--- a/data/shaders/objectref_pass2.frag
+++ b/data/shaders/objectref_pass2.frag
@@ -1,14 +1,16 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
+layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
+uniform sampler2D SpecMap;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@@ -20,6 +22,6 @@ void main(void)
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
if (col.a * color.a < 0.5) discard;
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(col.xyz * LightFactor, 1.);
+ float specmap = texture(SpecMap, uv).g;
+ FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}
diff --git a/data/shaders/primitive2dlist.vert b/data/shaders/primitive2dlist.vert
new file mode 100644
index 000000000..ceb835a89
--- /dev/null
+++ b/data/shaders/primitive2dlist.vert
@@ -0,0 +1,30 @@
+#if __VERSION__ >= 330
+layout(location = 0) in vec3 Position;
+layout(location = 1) in vec3 Normal;
+layout(location = 2) in vec4 Color;
+layout(location = 3) in vec2 Texcoord;
+layout(location = 4) in vec2 SecondTexcoord;
+layout(location = 5) in vec3 Tangent;
+layout(location = 6) in vec3 Bitangent;
+#else
+in vec3 Position;
+in vec3 Normal;
+in vec4 Color;
+in vec2 Texcoord;
+in vec2 SecondTexcoord;
+in vec3 Tangent;
+in vec3 Bitangent;
+#endif
+
+out vec2 uv;
+out vec4 color;
+
+void main(void)
+{
+ color = Color.zyxw;
+ vec3 P = Position / vec3(screen, 1.);
+ P = 2. * P - 1.;
+ P.y *= -1;
+ gl_Position = vec4(P, 1.);
+ uv = Texcoord;
+}
diff --git a/data/shaders/rh.frag b/data/shaders/rh.frag
index 17eadd2af..89fcd3fcb 100644
--- a/data/shaders/rh.frag
+++ b/data/shaders/rh.frag
@@ -9,6 +9,7 @@ uniform mat4 RSMMatrix;
uniform sampler2D dtex;
uniform sampler2D ctex;
uniform sampler2D ntex;
+uniform vec3 suncol;
flat in int slice;
layout (location = 0) out vec4 SHRed;
@@ -63,7 +64,7 @@ void loop(in int i,
float dotprod = max(dot(RSM_to_RH_dir, normal.xyz), 0.);
float factor = dotprod / (0.1 + dist * dist);
- vec3 color = RSMAlbedo.rgb * factor;
+ vec3 color = RSMAlbedo.rgb * factor * suncol.rgb;
SHr += DirToSh(RSM_to_RH_dir, color.r);
SHg += DirToSh(RSM_to_RH_dir, color.g);
diff --git a/data/shaders/splatting.frag b/data/shaders/splatting.frag
index d302908d2..acc6fabc3 100644
--- a/data/shaders/splatting.frag
+++ b/data/shaders/splatting.frag
@@ -22,7 +22,7 @@ varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
-vec3 getLightFactor(float specMapValue);
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
// Splatting part
@@ -46,6 +46,5 @@ void main() {
splatting.b * detail2 +
max(0., (1.0 - splatting.r - splatting.g - splatting.b)) * detail3;
- vec3 LightFactor = getLightFactor(1.);
- FragColor = vec4(splatted.xyz * LightFactor, 1.);
+ FragColor = vec4(getLightFactor(splatted.xyz, vec3(1.), 0.), 1.);
}
diff --git a/data/shaders/utils/getLightFactor.frag b/data/shaders/utils/getLightFactor.frag
index 9bf4cdf58..7d974d56d 100644
--- a/data/shaders/utils/getLightFactor.frag
+++ b/data/shaders/utils/getLightFactor.frag
@@ -8,12 +8,12 @@ uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
#endif
-vec3 getLightFactor(float specMapValue)
+vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue)
{
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
- vec3 tmp = DiffuseComponent + SpecularComponent * specMapValue;
+ vec3 tmp = diffuseMatColor * DiffuseComponent * (1. - specMapValue) + specularMatColor * SpecularComponent * specMapValue;
return tmp * ao;
}
\ No newline at end of file
diff --git a/src/achievements/achievement_info.cpp b/src/achievements/achievement_info.cpp
index 8763ba8e6..b2e28888c 100644
--- a/src/achievements/achievement_info.cpp
+++ b/src/achievements/achievement_info.cpp
@@ -35,6 +35,7 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
m_id = 0;
m_title = "";
m_description = "";
+ m_is_secret = false;
bool all;
all = input->get("id", &m_id ) &&
input->get("title", &m_title ) &&
@@ -69,6 +70,7 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
else
Log::warn("AchievementInfo", "Achievement check type '%s' unknown.",
s.c_str());
+ input->get("secret", &m_is_secret);
// Now load the goal nodes
for (unsigned int n = 0; n < input->getNumNodes(); n++)
diff --git a/src/achievements/achievement_info.hpp b/src/achievements/achievement_info.hpp
index 648671794..c9b98e13d 100644
--- a/src/achievements/achievement_info.hpp
+++ b/src/achievements/achievement_info.hpp
@@ -94,6 +94,9 @@ private:
/** Determines when the achievement needs to be reset */
ResetType m_reset_type;
+ /** A secret achievement has its progress not shown. */
+ bool m_is_secret;
+
public:
AchievementInfo(const XMLNode * input);
virtual ~AchievementInfo() {};
@@ -119,6 +122,9 @@ public:
/** Returns the check type for this achievement. */
AchievementCheckType getCheckType() const { return m_check_type; }
// ------------------------------------------------------------------------
+ /** Returns if this achievement is a secret achievement. */
+ bool isSecret() const { return m_is_secret; }
+ // ------------------------------------------------------------------------
}; // class AchievementInfo
diff --git a/src/audio/dummy_sfx.hpp b/src/audio/dummy_sfx.hpp
index 9840c2233..765912902 100644
--- a/src/audio/dummy_sfx.hpp
+++ b/src/audio/dummy_sfx.hpp
@@ -23,7 +23,6 @@
#include "audio/sfx_base.hpp"
-
/**
* \brief Dummy sound when ogg or openal aren't available
* \ingroup audio
@@ -31,25 +30,35 @@
class DummySFX : public SFXBase
{
public:
- DummySFX(SFXBuffer* buffer, bool positional, float gain) {}
+ DummySFX(SFXBuffer* buffer, bool positional,
+ float gain) {}
virtual ~DummySFX() {}
/** Late creation, if SFX was initially disabled */
- virtual bool init() { return true; }
-
- virtual void position(const Vec3 &position) {}
- virtual void setLoop(bool status) {}
- virtual void play() {}
- virtual void stop() {}
- virtual void pause() {}
- virtual void resume() {}
- virtual void speed(float factor) {}
- virtual void volume(float gain) {}
- virtual SFXManager::SFXStatus getStatus() { return SFXManager::SFX_STOPPED; }
- virtual void onSoundEnabledBack() {}
- virtual void setRolloff(float rolloff) {}
-
- virtual const SFXBuffer* getBuffer() const { return NULL; }
+ virtual bool init() { return true; }
+ virtual bool isLooped() { return false; }
+ virtual void updatePlayingSFX(float dt) {}
+ virtual void setLoop(bool status) {}
+ virtual void reallySetLoop(bool status) {}
+ virtual void setPosition(const Vec3 &p) {}
+ virtual void reallySetPosition(const Vec3 &p) {}
+ virtual void play() {}
+ virtual void reallyPlayNow() {}
+ virtual void stop() {}
+ virtual void reallyStopNow() {}
+ virtual void pause() {}
+ virtual void reallyPauseNow() {}
+ virtual void resume() {}
+ virtual void reallyResumeNow() {}
+ virtual void deleteSFX() { delete this; }
+ virtual void setSpeed(float factor) {}
+ virtual void reallySetSpeed(float factor) {}
+ virtual void setVolume(float gain) {}
+ virtual void reallySetVolume(float gain) {}
+ virtual SFXStatus getStatus() { return SFX_STOPPED; }
+ virtual void onSoundEnabledBack() {}
+ virtual void setRolloff(float rolloff) {}
+ virtual const SFXBuffer* getBuffer() const { return NULL; }
}; // DummySFX
diff --git a/src/audio/sfx_base.hpp b/src/audio/sfx_base.hpp
index 033d57c05..4e647b87c 100644
--- a/src/audio/sfx_base.hpp
+++ b/src/audio/sfx_base.hpp
@@ -42,26 +42,43 @@ class Vec3;
class SFXBase : public NoCopy
{
public:
+ /** Status of a sound effect. */
+ enum SFXStatus
+ {
+ SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
+ SFX_NOT_INITIALISED = 3
+ };
+
virtual ~SFXBase() {}
/** Late creation, if SFX was initially disabled */
- virtual bool init() = 0;
- virtual void position(const Vec3 &position) = 0;
- virtual void setLoop(bool status) = 0;
- virtual void play() = 0;
- virtual void reallyPlayNow() = 0;
- virtual void stop() = 0;
- virtual void pause() = 0;
- virtual void resume() = 0;
- virtual void speed(float factor) = 0;
- virtual void volume(float gain) = 0;
- virtual void setMasterVolume(float gain) = 0;
- virtual void onSoundEnabledBack() = 0;
- virtual void setRolloff(float rolloff) = 0;
- virtual const SFXBuffer* getBuffer() const = 0;
- virtual SFXManager::SFXStatus getStatus() = 0;
+ virtual bool init() = 0;
+ virtual bool isLooped() = 0;
+ virtual void updatePlayingSFX(float dt) = 0;
+ virtual void setPosition(const Vec3 &p) = 0;
+ virtual void reallySetPosition(const Vec3 &p) = 0;
+ virtual void setLoop(bool status) = 0;
+ virtual void reallySetLoop(bool status) = 0;
+ virtual void play() = 0;
+ virtual void reallyPlayNow() = 0;
+ virtual void stop() = 0;
+ virtual void reallyStopNow() = 0;
+ virtual void pause() = 0;
+ virtual void reallyPauseNow() = 0;
+ virtual void resume() = 0;
+ virtual void reallyResumeNow() = 0;
+ virtual void deleteSFX() = 0;
+ virtual void setSpeed(float factor) = 0;
+ virtual void reallySetSpeed(float factor) = 0;
+ virtual void setVolume(float gain) = 0;
+ virtual void reallySetVolume(float gain) = 0;
+ virtual void setMasterVolume(float gain) = 0;
+ virtual void onSoundEnabledBack() = 0;
+ virtual void setRolloff(float rolloff) = 0;
+ virtual const SFXBuffer* getBuffer() const = 0;
+ virtual SFXStatus getStatus() = 0;
-}; // SfxBase
+}; // SFXBase
#endif // HEADER_SFX_HPP
diff --git a/src/audio/sfx_buffer.cpp b/src/audio/sfx_buffer.cpp
index 910b29f88..0ac37f2d2 100644
--- a/src/audio/sfx_buffer.cpp
+++ b/src/audio/sfx_buffer.cpp
@@ -36,27 +36,37 @@
#endif
//----------------------------------------------------------------------------
-
+/** Creates a sfx. The parameter are taken from the parameters:
+ * \param file File name of the buffer.
+ * \param positional If the sfx is positional.
+ * \param rolloff Rolloff value of this sfx.
+ * \param max_dist Maximum distance the sfx can be heard.
+ * \param gain Gain value of this sfx.
+ */
SFXBuffer::SFXBuffer(const std::string& file,
bool positional,
float rolloff,
- float max_width,
+ float max_dist,
float gain)
{
m_buffer = 0;
m_gain = 1.0f;
m_rolloff = 0.1f;
m_loaded = false;
- m_max_dist = max_width;
+ m_max_dist = max_dist;
+ m_duration = -1.0f;
m_file = file;
m_rolloff = rolloff;
m_positional = positional;
m_gain = gain;
-}
+} // SFXBuffer
//----------------------------------------------------------------------------
-
+/** Constructor getting the sfx parameters from an XML node.
+ * \param file File name of the data.
+ * \param node XML Node with the data for this sfx.
+ */
SFXBuffer::SFXBuffer(const std::string& file,
const XMLNode* node)
{
@@ -64,6 +74,7 @@ SFXBuffer::SFXBuffer(const std::string& file,
m_gain = 1.0f;
m_rolloff = 0.1f;
m_max_dist = 300.0f;
+ m_duration = -1.0f;
m_positional = false;
m_loaded = false;
m_file = file;
@@ -72,10 +83,15 @@ SFXBuffer::SFXBuffer(const std::string& file,
node->get("positional", &m_positional );
node->get("volume", &m_gain );
node->get("max_dist", &m_max_dist );
-}
+ node->get("duration", &m_duration );
+} // SFXBuffer(XMLNode)
//----------------------------------------------------------------------------
-
+/** \brief load the buffer from file into OpenAL.
+ * \note If this buffer is already loaded, this call does nothing and
+ * returns false.
+ * \return Whether loading was successful.
+ */
bool SFXBuffer::load()
{
if (UserConfigParams::m_sfx == false) return false;
@@ -103,9 +119,13 @@ bool SFXBuffer::load()
m_loaded = true;
return true;
-}
+} // load
//----------------------------------------------------------------------------
+/** \brief Frees the loaded buffer.
+ * Cannot appear in destructor because copy-constructors may be used,
+ * and the OpenAL source must not be deleted on a copy
+ */
void SFXBuffer::unload()
{
@@ -117,7 +137,7 @@ void SFXBuffer::unload()
}
#endif
m_loaded = false;
-}
+} // unload
//----------------------------------------------------------------------------
/** Load a vorbis file into an OpenAL buffer
@@ -164,7 +184,7 @@ bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
if(!data)
{
ov_clear(&oggFile);
- Log::error("SFXBuffer", "[SFXBuffer] loadVorbisBuffer() - Error : LoadVorbisBuffer() - couldn't allocate decode buffer\n");
+ Log::error("SFXBuffer", "[SFXBuffer] Could not allocate decode buffer.");
return false;
}
@@ -188,9 +208,21 @@ bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
ov_clear(&oggFile);
fclose(file);
+
+ // Allow the xml data to overwrite the duration, but if there is no
+ // duration (which is the norm), compute it:
+ if(m_duration < 0)
+ {
+ ALint buffer_size, frequency, bits_per_sample, channels;
+ alGetBufferi(buffer, AL_SIZE, &buffer_size );
+ alGetBufferi(buffer, AL_FREQUENCY, &frequency );
+ alGetBufferi(buffer, AL_CHANNELS, &channels );
+ alGetBufferi(buffer, AL_BITS, &bits_per_sample);
+ m_duration = float(buffer_size) / (frequency*channels*(bits_per_sample / 8));
+ }
return success;
#else
return false;
#endif
-}
+} // loadVorbisBuffer
diff --git a/src/audio/sfx_buffer.hpp b/src/audio/sfx_buffer.hpp
index 98ffbc8e4..e0583b67c 100644
--- a/src/audio/sfx_buffer.hpp
+++ b/src/audio/sfx_buffer.hpp
@@ -46,18 +46,32 @@ class SFXBuffer
{
private:
+ LEAK_CHECK()
+
/** Whether the contents of the file was loaded */
bool m_loaded;
/** The file that contains the OGG audio data */
std::string m_file;
+ /** The openal buffer id. */
ALuint m_buffer;
+
+ /** If the sound is positional. */
bool m_positional;
+
+ /** The roll-off value. */
float m_rolloff;
+
+ /** The volume gain value. */
float m_gain;
+
+ /** Maximum distance the sfx can be heard. */
float m_max_dist;
+ /** Duration of the sfx. */
+ float m_duration;
+
bool loadVorbisBuffer(const std::string &name, ALuint buffer);
public:
@@ -70,41 +84,43 @@ public:
SFXBuffer(const std::string& file,
const XMLNode* node);
-
~SFXBuffer()
{
- }
+ } // ~SFXBuffer
- /**
- * \brief load the buffer from file into OpenAL.
- * \note If this buffer is already loaded, this call does nothing and returns false
- * \return whether loading was successful
- */
- bool load();
- /**
- * \brief Frees the loaded buffer
- * Cannot appear in destructor because copy-constructors may be used,
- * and the OpenAL source must not be deleted on a copy
- */
- void unload();
+ bool load();
+ void unload();
+ // ------------------------------------------------------------------------
/** \return whether this buffer was loaded from disk */
- bool isLoaded() const { return m_loaded; }
-
+ bool isLoaded() const { return m_loaded; }
+ // ------------------------------------------------------------------------
/** Only returns a valid buffer if isLoaded() returned true */
- ALuint getBufferID() const { return m_buffer; }
+ ALuint getBufferID() const { return m_buffer; }
+ // ------------------------------------------------------------------------
+ /** Returns if the buffer is positional. */
+ bool isPositional() const { return m_positional; }
+ // ------------------------------------------------------------------------
+ /** Returns the rolloff value of this buffer. */
+ float getRolloff() const { return m_rolloff; }
+ // ------------------------------------------------------------------------
+ /** Returns the gain for this sfx. */
+ float getGain() const { return m_gain; }
+ // ------------------------------------------------------------------------
+ /** Returns the maximum distance this sfx can be heard. */
+ float getMaxDist() const { return m_max_dist; }
+ // ------------------------------------------------------------------------
+ /** Returns the file name of this buffer. */
+ const std::string& getFileName() const { return m_file; }
+ // ------------------------------------------------------------------------
+ /** Sets if this buffer is positional or not. */
+ void setPositional(bool positional) { m_positional = positional; }
+ // ------------------------------------------------------------------------
+ /** Returns how long this buffer will play. */
+ float getDuration() const { return m_duration; }
- bool isPositional() const { return m_positional; }
- float getRolloff() const { return m_rolloff; }
- float getGain() const { return m_gain; }
- float getMaxDist() const { return m_max_dist; }
- std::string getFileName() const { return m_file; }
-
- void setPositional(bool positional) { m_positional = positional; }
-
- LEAK_CHECK()
-};
+}; // class SFXBuffer
#endif // HEADER_SFX_BUFFER_HPP
diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp
index 1bfd2c54e..1b45a8a5c 100644
--- a/src/audio/sfx_manager.cpp
+++ b/src/audio/sfx_manager.cpp
@@ -74,7 +74,10 @@ SFXManager::SFXManager()
m_initialized = music_manager->initialized();
m_master_gain = UserConfigParams::m_sfx_volume;
// Init position, since it can be used before positionListener is called.
- m_position = Vec3(0,0,0);
+ // No need to use lock here, since the thread will be created later.
+ m_listener_position.getData() = Vec3(0, 0, 0);
+ m_listener_front = Vec3(0, 0, 1);
+ m_listener_up = Vec3(0, 1, 0);
loadSfx();
@@ -98,17 +101,15 @@ SFXManager::SFXManager()
delete m_thread_id.getData();
m_thread_id.unlock();
m_thread_id.setAtomic(0);
- Log::error("HTTP Manager", "Could not create thread, error=%d.",
+ Log::error("SFXManager", "Could not create thread, error=%d.",
errno);
}
pthread_attr_destroy(&attr);
- if (!sfxAllowed()) return;
-
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
- m_sfx_to_play.lock();
- m_sfx_to_play.getData().clear();
- m_sfx_to_play.unlock();
+ m_sfx_commands.lock();
+ m_sfx_commands.getData().clear();
+ m_sfx_commands.unlock();
} // SoundManager
@@ -124,13 +125,15 @@ SFXManager::~SFXManager()
pthread_cond_destroy(&m_cond_request);
// ---- clear m_all_sfx
- const int sfx_amount = (int) m_all_sfx.size();
+ // not strictly necessary, but might avoid copy&paste problems
+ m_all_sfx.lock();
+ const int sfx_amount = (int) m_all_sfx.getData().size();
for (int n=0; n::iterator i = m_quick_sounds.begin();
@@ -158,32 +161,84 @@ SFXManager::~SFXManager()
} // ~SFXManager
//----------------------------------------------------------------------------
-/** Adds a sound effect to the queue of sfx to be started by the sfx manager.
- * Starting a sfx can sometimes cause a 5ms delay, so it is done in a
- * separate thread.
+/** Adds a sound effect command to the queue of the sfx manager. Openal
+ * commands can sometimes cause a 5ms delay, so it is done in a separate
+ * thread.
+ * \param command The command to execute.
* \param sfx The sound effect to be started.
*/
-void SFXManager::queue(SFXBase *sfx)
+void SFXManager::queue(SFXCommands command, SFXBase *sfx)
{
- // Don't add sfx that are either not working correctly (e.g. because sfx
- // are disabled);
- if(sfx && sfx->getStatus()==SFX_UNKNOWN ) return;
-
- m_sfx_to_play.lock();
- m_sfx_to_play.getData().push_back(sfx);
- m_sfx_to_play.unlock();
- // Wake up the sfx thread
- pthread_cond_signal(&m_cond_request);
-
+ SFXCommand *sfx_command = new SFXCommand(command, sfx);
+ queueCommand(sfx_command);
} // queue
+//----------------------------------------------------------------------------
+/** Adds a sound effect command with a single floating point parameter to the
+ * queue of the sfx manager. Openal commands can sometimes cause a 5ms delay,
+ * so it is done in a separate thread.
+ * \param command The command to execute.
+ * \param sfx The sound effect to be started.
+ * \param f Floating point parameter for the command.
+ */
+void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f)
+{
+ SFXCommand *sfx_command = new SFXCommand(command, sfx, f);
+ queueCommand(sfx_command);
+} // queue(float)
+
+//----------------------------------------------------------------------------
+/** Adds a sound effect command with a Vec3 parameter to the queue of the sfx
+ * manager. Openal commands can sometimes cause a 5ms delay, so it is done in
+ * a separate thread.
+ * \param command The command to execute.
+ * \param sfx The sound effect to be started.
+ * \param p A Vec3 parameter for the command.
+ */
+void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
+{
+ SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
+ queueCommand(sfx_command);
+} // queue (Vec3)
+
+//----------------------------------------------------------------------------
+/** Enqueues a command to the sfx queue threadsafe. Then signal the
+ * sfx manager to wake up.
+ * \param command Pointer to the command to queue up.
+ */
+void SFXManager::queueCommand(SFXCommand *command)
+{
+ m_sfx_commands.lock();
+ if(m_sfx_commands.getData().size() > 20*race_manager->getNumberOfKarts()+20)
+ {
+ if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
+ command->m_command==SFX_PLAY || command->m_command==SFX_SPEED )
+ {
+ delete command;
+ static int count_messages = 0;
+ if(count_messages < 5)
+ {
+ Log::warn("SFXManager", "Throttling sfx - queue size %d",
+ m_sfx_commands.getData().size());
+ count_messages++;
+ }
+ m_sfx_commands.unlock();
+ return;
+ } // if throttling
+ }
+ m_sfx_commands.getData().push_back(command);
+ m_sfx_commands.unlock();
+} // queueCommand
+
//----------------------------------------------------------------------------
/** Puts a NULL request into the queue, which will trigger the thread to
* exit.
*/
void SFXManager::stopThread()
{
- queue(NULL);
+ queue(SFX_EXIT);
+ // Make sure the thread wakes up.
+ pthread_cond_signal(&m_cond_request);
} // stopThread
//----------------------------------------------------------------------------
@@ -198,40 +253,68 @@ void* SFXManager::mainLoop(void *obj)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- me->m_sfx_to_play.lock();
+ me->m_sfx_commands.lock();
// Wait till we have an empty sfx in the queue
- while (me->m_sfx_to_play.getData().empty() ||
- me->m_sfx_to_play.getData().front()!=NULL )
+ while (me->m_sfx_commands.getData().empty() ||
+ me->m_sfx_commands.getData().front()->m_command!=SFX_EXIT)
{
- bool empty = me->m_sfx_to_play.getData().empty();
+ bool empty = me->m_sfx_commands.getData().empty();
// Wait in cond_wait for a request to arrive. The 'while' is necessary
// since "spurious wakeups from the pthread_cond_wait ... may occur"
// (pthread_cond_wait man page)!
while (empty)
{
- pthread_cond_wait(&me->m_cond_request, me->m_sfx_to_play.getMutex());
- empty = me->m_sfx_to_play.getData().empty();
+ pthread_cond_wait(&me->m_cond_request, me->m_sfx_commands.getMutex());
+ empty = me->m_sfx_commands.getData().empty();
}
+ SFXCommand *current = me->m_sfx_commands.getData().front();
+ me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
- SFXBase *current = me->m_sfx_to_play.getData().front();
- me->m_sfx_to_play.getData().erase(me->m_sfx_to_play.getData().begin());
-
- if (!current) // empty sfx indicates to abort the sfx manager
+ if (current->m_command == SFX_EXIT)
break;
-
- me->m_sfx_to_play.unlock();
- current->reallyPlayNow();
- me->m_sfx_to_play.lock();
+ me->m_sfx_commands.unlock();
+ switch(current->m_command)
+ {
+ case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
+ case SFX_STOP: current->m_sfx->reallyStopNow(); break;
+ case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
+ case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
+ case SFX_SPEED: current->m_sfx->reallySetSpeed(
+ current->m_parameter.getX()); break;
+ case SFX_POSITION: current->m_sfx->reallySetPosition(
+ current->m_parameter); break;
+ case SFX_VOLUME: current->m_sfx->reallySetVolume(
+ current->m_parameter.getX()); break;
+ case SFX_LOOP: current->m_sfx->reallySetLoop(
+ current->m_parameter.getX()!=0); break;
+ case SFX_DELETE: {
+ me->deleteSFX(current->m_sfx); break;
+ }
+ case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
+ case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
+ case SFX_LISTENER: me->reallyPositionListenerNow(); break;
+ case SFX_UPDATE: me->reallyUpdateNow(current); break;
+ default: assert("Not yet supported.");
+ }
+ delete current;
+ current = NULL;
+ me->m_sfx_commands.lock();
} // while
+ // Clean up memory to avoid leak detection
+ while(!me->m_sfx_commands.getData().empty())
+ {
+ delete me->m_sfx_commands.getData().front();
+ me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
+ }
return NULL;
} // mainLoop
//----------------------------------------------------------------------------
-/** Called then sound is globally switched on or off. It either pauses or
+/** Called when sound is globally switched on or off. It either pauses or
* resumes all sound effects.
* \param on If sound is switched on or off.
*/
@@ -248,18 +331,30 @@ void SFXManager::soundToggled(const bool on)
}
resumeAll();
-
- const int sfx_amount = (int)m_all_sfx.size();
+ m_all_sfx.lock();
+ const int sfx_amount = (int)m_all_sfx.getData().size();
for (int n=0; nonSoundEnabledBack();
+ m_all_sfx.getData()[n]->onSoundEnabledBack();
}
+ m_all_sfx.unlock();
}
else
{
+ // First stop all sfx that are not looped
+ const int sfx_amount = (int)m_all_sfx.getData().size();
+ m_all_sfx.lock();
+ for (int i=0; iisLooped())
+ {
+ m_all_sfx.getData()[i]->reallyStopNow();
+ }
+ }
+ m_all_sfx.unlock();
pauseAll();
}
-}
+} // soundToggled
//----------------------------------------------------------------------------
/** Returns if sfx can be played. This means sfx are enabled and
@@ -359,7 +454,7 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
}
if (UserConfigParams::logMisc())
- Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
+ Log::debug("SFXManager", "Loading SFX %s", sfx_file.c_str());
if (load && buffer->load()) return buffer;
@@ -379,7 +474,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if (node->get("filename", &filename) == 0)
{
Log::error("SFXManager",
- "/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
+ "The 'filename' attribute is mandatory in the SFX XML file!");
return NULL;
}
@@ -388,7 +483,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
{
Log::error("SFXManager",
- "There is already a sfx named '%s' installed - new one is ignored.\n",
+ "There is already a sfx named '%s' installed - new one is ignored.",
sfx_name.c_str());
return NULL;
}
@@ -437,7 +532,12 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
sfx->setMasterVolume(m_master_gain);
- if (add_to_SFX_list) m_all_sfx.push_back(sfx);
+ if (add_to_SFX_list)
+ {
+ m_all_sfx.lock();
+ m_all_sfx.getData().push_back(sfx);
+ m_all_sfx.unlock();
+ }
return sfx;
} // createSoundSource
@@ -451,7 +551,7 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
{
Log::error("SFXManager",
"SFXManager::createSoundSource could not find the "
- "requested sound effect : '%s'\n", name.c_str());
+ "requested sound effect : '%s'.", name.c_str());
return NULL;
}
@@ -489,6 +589,38 @@ void SFXManager::deleteSFXMapping(const std::string &name)
} // deleteSFXMapping
+//----------------------------------------------------------------------------
+/** Make sures that the sfx thread is started at least one per frame. It also
+ * adds an update command for the music manager.
+ * \param dt Time step size.
+ */
+void SFXManager::update(float dt)
+{
+ queue(SFX_UPDATE, NULL, dt);
+ // Wake up the sfx thread to handle all queued up audio commands.
+ pthread_cond_signal(&m_cond_request);
+} // update
+
+//----------------------------------------------------------------------------
+/** Updates the status of all playing sfx (to test if they are finished).
+ * This function is executed once per thread (triggered by the
+*/
+void SFXManager::reallyUpdateNow(SFXCommand *current)
+{
+ assert(current->m_command==SFX_UPDATE);
+ float dt = current->m_parameter.getX();
+ music_manager->update(dt);
+ m_all_sfx.lock();
+ for (std::vector::iterator i = m_all_sfx.getData().begin();
+ i != m_all_sfx.getData().end(); i++)
+ {
+ if((*i)->getStatus()==SFXBase::SFX_PLAYING)
+ (*i)->updatePlayingSFX(dt);
+ } // for i in m_all_sfx
+ m_all_sfx.unlock();
+
+} // reallyUpdateNow
+
//----------------------------------------------------------------------------
/** Delete a sound effect object, and removes it from the internal list of
* all SFXs. This call deletes the object, and removes it from the list of
@@ -497,59 +629,85 @@ void SFXManager::deleteSFXMapping(const std::string &name)
*/
void SFXManager::deleteSFX(SFXBase *sfx)
{
- if(sfx) sfx->stop();
+ if(sfx) sfx->reallyStopNow();
std::vector::iterator i;
- i=std::find(m_all_sfx.begin(), m_all_sfx.end(), sfx);
+
+ // The whole block needs to be locked, otherwise the iterator
+ // could become invalid.
+ m_all_sfx.lock();
+ i=std::find(m_all_sfx.getData().begin(), m_all_sfx.getData().end(), sfx);
- if(i==m_all_sfx.end())
+ if(i==m_all_sfx.getData().end())
{
Log::warn("SFXManager",
- "SFXManager::deleteSFX : Warning: sfx not found in list.");
+ "SFXManager::deleteSFX : Warning: sfx '%s' %lx not found in list.",
+ sfx->getBuffer()->getFileName().c_str(), sfx);
+ m_all_sfx.unlock();
return;
}
+ m_all_sfx.getData().erase(i);
+ m_all_sfx.unlock();
+
delete sfx;
-
- m_all_sfx.erase(i);
-
} // deleteSFX
+//----------------------------------------------------------------------------
+/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
+ * otherwise not possible to determine which SFX must be resumed (i.e. were
+ * actually playing at the time pause was called).
+ */
+void SFXManager::pauseAll()
+{
+ if (!sfxAllowed()) return;
+ queue(SFX_PAUSE_ALL);
+} // pauseAll
+
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called.
*/
-void SFXManager::pauseAll()
+void SFXManager::reallyPauseAllNow()
{
- for (std::vector::iterator i=m_all_sfx.begin();
- i!=m_all_sfx.end(); i++)
+ m_all_sfx.lock();
+ for (std::vector::iterator i= m_all_sfx.getData().begin();
+ i!=m_all_sfx.getData().end(); i++)
{
- (*i)->pause();
+ (*i)->reallyPauseNow();
} // for i in m_all_sfx
+ m_all_sfx.unlock();
} // pauseAll
//----------------------------------------------------------------------------
-/**
- * Resumes all paused SFXs. If sound is disabled, does nothing.
+/** Resumes all paused SFXs. If sound is disabled, does nothing.
*/
void SFXManager::resumeAll()
{
// ignore unpausing if sound is disabled
if (!sfxAllowed()) return;
+ queue(SFX_RESUME_ALL);
+} // resumeAll
- for (std::vector::iterator i=m_all_sfx.begin();
- i!=m_all_sfx.end(); i++)
+//----------------------------------------------------------------------------
+/** Resumes all paused SFXs. If sound is disabled, does nothing.
+ */
+void SFXManager::reallyResumeAllNow()
+{
+ m_all_sfx.lock();
+ for (std::vector::iterator i =m_all_sfx.getData().begin();
+ i!=m_all_sfx.getData().end(); i++)
{
- SFXStatus status = (*i)->getStatus();
- // Initial happens when
- if (status==SFX_PAUSED) (*i)->resume();
+ (*i)->reallyResumeNow();
} // for i in m_all_sfx
+ m_all_sfx.unlock();
} // resumeAll
//-----------------------------------------------------------------------------
/** Returns whether or not an openal error has occurred. If so, an error
* message is printed containing the given context.
* \param context Context to specify in the error message.
+ * \return True if no error happened.
*/
bool SFXManager::checkError(const std::string &context)
{
@@ -580,11 +738,13 @@ void SFXManager::setMasterSFXVolume(float gain)
// regular SFX
{
- for (std::vector::iterator i=m_all_sfx.begin();
- i!=m_all_sfx.end(); i++)
+ m_all_sfx.lock();
+ for (std::vector::iterator i =m_all_sfx.getData().begin();
+ i!=m_all_sfx.getData().end(); i++)
{
(*i)->setMasterVolume(m_master_gain);
} // for i in m_all_sfx
+ m_all_sfx.unlock();
}
// quick SFX
@@ -621,28 +781,51 @@ const std::string SFXManager::getErrorString(int err)
/** Sets the position and orientation of the listener.
* \param position Position of the listener.
* \param front Which way the listener is facing.
+ * \param up The up direction of the listener.
*/
-void SFXManager::positionListener(const Vec3 &position, const Vec3 &front)
+void SFXManager::positionListener(const Vec3 &position, const Vec3 &front,
+ const Vec3 &up)
+{
+ m_listener_position.lock();
+ m_listener_position.getData() = position;
+ m_listener_front = front;
+ m_listener_up = up;
+ m_listener_position.unlock();
+ queue(SFX_LISTENER);
+} // positionListener
+
+//-----------------------------------------------------------------------------
+/** Sets the position and orientation of the listener.
+ * \param position Position of the listener.
+ * \param front Which way the listener is facing.
+ */
+void SFXManager::reallyPositionListenerNow()
{
#if HAVE_OGGVORBIS
if (!UserConfigParams::m_sfx || !m_initialized) return;
- m_position = position;
+ m_listener_position.lock();
+ {
- //forward vector
- m_listenerVec[0] = front.getX();
- m_listenerVec[1] = front.getY();
- m_listenerVec[2] = front.getZ();
+ //forward vector
+ float orientation[6];
+ orientation[0] = m_listener_front.getX();
+ orientation[1] = m_listener_front.getY();
+ orientation[2] = m_listener_front.getZ();
- //up vector
- m_listenerVec[3] = 0;
- m_listenerVec[4] = 0;
- m_listenerVec[5] = 1;
+ //up vector
+ orientation[3] = m_listener_up.getX();
+ orientation[4] = m_listener_up.getY();
+ orientation[5] = m_listener_up.getZ();
+
+ const Vec3 &pos = m_listener_position.getData();
+ alListener3f(AL_POSITION, pos.getX(), pos.getY(), pos.getZ());
+ alListenerfv(AL_ORIENTATION, orientation);
+ }
+ m_listener_position.unlock();
- alListener3f(AL_POSITION, position.getX(), position.getY(), position.getZ());
- alListenerfv(AL_ORIENTATION, m_listenerVec);
#endif
-}
+} // reallyPositionListenerNow
//-----------------------------------------------------------------------------
/** Positional sound is cool, but creating a new object just to play a simple
diff --git a/src/audio/sfx_manager.hpp b/src/audio/sfx_manager.hpp
index 4af8f6e22..47e4cbb74 100644
--- a/src/audio/sfx_manager.hpp
+++ b/src/audio/sfx_manager.hpp
@@ -19,6 +19,7 @@
#ifndef HEADER_SFX_MANAGER_HPP
#define HEADER_SFX_MANAGER_HPP
+#include "utils/leak_check.hpp"
#include "utils/no_copy.hpp"
#include "utils/synchronised.hpp"
#include "utils/vec3.hpp"
@@ -57,6 +58,26 @@ private:
public:
+ /** The various commands to be executed by the sfx manager thread
+ * for each sfx. */
+ enum SFXCommands
+ {
+ SFX_PLAY = 1,
+ SFX_STOP,
+ SFX_PAUSE,
+ SFX_PAUSE_ALL,
+ SFX_RESUME,
+ SFX_RESUME_ALL,
+ SFX_DELETE,
+ SFX_SPEED,
+ SFX_POSITION,
+ SFX_VOLUME,
+ SFX_LOOP,
+ SFX_LISTENER,
+ SFX_UPDATE,
+ SFX_EXIT,
+ }; // SFXCommands
+
/**
* Entries for custom SFX sounds. These are unique for each kart.
* eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN)
@@ -76,34 +97,68 @@ public:
NUM_CUSTOMS
};
- /** Status of a sound effect. */
- enum SFXStatus
- {
- SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
- SFX_INITIAL = 3
- };
-
private:
- /** Listener position */
- Vec3 m_position;
+ /** Data structure for the queue, which stores a sfx and the command to
+ * execute for it. */
+ class SFXCommand : public NoCopy
+ {
+ private:
+ LEAK_CHECK()
+ public:
+ /** The sound effect for which the command should be executed. */
+ SFXBase *m_sfx;
+ /** The command to execute. */
+ SFXCommands m_command;
+ /** Optional parameter for commands that need more input. */
+ Vec3 m_parameter;
+ // --------------------------------------------------------------------
+ SFXCommand(SFXCommands command, SFXBase *base)
+ {
+ m_command = command;
+ m_sfx = base;
+ } // SFXCommand()
+ // --------------------------------------------------------------------
+ SFXCommand(SFXCommands command, SFXBase *base, float parameter)
+ {
+ m_command = command;
+ m_sfx = base;
+ m_parameter.setX(parameter);
+ } // SFXCommand(float)
+ // --------------------------------------------------------------------
+ SFXCommand(SFXCommands command, SFXBase *base, const Vec3 ¶meter)
+ {
+ m_command = command;
+ m_sfx = base;
+ m_parameter = parameter;
+ } // SFXCommand(Vec3)
+ }; // SFXCommand
+ // ========================================================================
+
+ /** The position of the listener. Its lock will be used to
+ * access m_listener_{position,front, up}. */
+ Synchronised m_listener_position;
+
+ /** The direction the listener is facing. */
+ Vec3 m_listener_front;
+
+ /** Up vector of the listener. */
+ Vec3 m_listener_up;
+
/** The buffers and info for all sound effects. These are shared among all
* instances of SFXOpenal. */
std::map m_all_sfx_types;
/** The actual instances (sound sources) */
- std::vector m_all_sfx;
+ Synchronised > m_all_sfx;
/** The list of sound effects to be played in the next update. */
- Synchronised< std::vector > m_sfx_to_play;
+ Synchronised< std::vector > m_sfx_commands;
/** To play non-positional sounds without having to create a new object for each */
std::map m_quick_sounds;
- /** listener vector (position vector + up vector) */
- float m_listenerVec[6];
-
/** If the sfx manager has been initialised. */
bool m_initialized;
@@ -121,10 +176,16 @@ private:
virtual ~SFXManager();
static void* mainLoop(void *obj);
+ void deleteSFX(SFXBase *sfx);
+ void queueCommand(SFXCommand *command);
+ void reallyPositionListenerNow();
+
public:
static void create();
static void destroy();
- void queue(SFXBase *sfx);
+ void queue(SFXCommands command, SFXBase *sfx=NULL);
+ void queue(SFXCommands command, SFXBase *sfx, float f);
+ void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
// ------------------------------------------------------------------------
/** Static function to get the singleton sfx manager. */
static SFXManager *get()
@@ -148,15 +209,18 @@ public:
const bool load = true);
SFXBase* createSoundSource(SFXBuffer* info,
- const bool addToSFXList=true,
+ const bool add_to_SFX_list=true,
const bool owns_buffer=false);
SFXBase* createSoundSource(const std::string &name,
const bool addToSFXList=true);
- void deleteSFX(SFXBase *sfx);
void deleteSFXMapping(const std::string &name);
void pauseAll();
+ void reallyPauseAllNow();
void resumeAll();
+ void reallyResumeAllNow();
+ void update(float dt);
+ void reallyUpdateNow(SFXCommand *current);
bool soundExist(const std::string &name);
void setMasterSFXVolume(float gain);
float getMasterSFXVolume() const { return m_master_gain; }
@@ -164,7 +228,8 @@ public:
static bool checkError(const std::string &context);
static const std::string getErrorString(int err);
- void positionListener(const Vec3 &position, const Vec3 &front);
+ void positionListener(const Vec3 &position,
+ const Vec3 &front, const Vec3 &up);
SFXBase* quickSound(const std::string &soundName);
/** Called when sound was muted/unmuted */
@@ -177,7 +242,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the current position of the listener. */
- Vec3 getListenerPos() const { return m_position; }
+ Vec3 getListenerPos() const { return m_listener_position.getData(); }
};
diff --git a/src/audio/sfx_openal.cpp b/src/audio/sfx_openal.cpp
index 83c503ca6..dafd3ce1f 100644
--- a/src/audio/sfx_openal.cpp
+++ b/src/audio/sfx_openal.cpp
@@ -1,7 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2006-2013 Patrick Ammann
-// Copyright (C) 2009-2013 Marianne Gagnon
+// Copyright (C) 2014 Joerg Henrichs
+// Copyright (C) 2006-2014 Patrick Ammann
+// Copyright (C) 2009-2014 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -23,8 +24,7 @@
#include "audio/sfx_buffer.hpp"
#include "config/user_config.hpp"
-#include "io/file_manager.hpp"
-#include "race/race_manager.hpp"
+#include "modes/world.hpp"
#include "utils/vs.hpp"
#ifdef __APPLE__
@@ -38,17 +38,20 @@
#include
#include
-SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBuffer) : SFXBase()
+SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
+ bool owns_buffer)
+ : SFXBase()
{
- m_soundBuffer = buffer;
- m_soundSource = 0;
- m_ok = false;
- m_positional = positional;
- m_defaultGain = gain;
- m_loop = false;
- m_gain = -1.0f;
- m_master_gain = 1.0f;
- m_owns_buffer = ownsBuffer;
+ m_sound_buffer = buffer;
+ m_sound_source = 0;
+ m_status = SFX_NOT_INITIALISED;
+ m_positional = positional;
+ m_default_gain = gain;
+ m_loop = false;
+ m_gain = -1.0f;
+ m_master_gain = 1.0f;
+ m_owns_buffer = owns_buffer;
+ m_play_time = 0.0f;
// Don't initialise anything else if the sfx manager was not correctly
// initialised. First of all the initialisation will not work, and it
@@ -60,74 +63,106 @@ SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBu
} // SFXOpenAL
//-----------------------------------------------------------------------------
-
+/** Deletes the sfx source, and if it owns the buffer, also deletes the sound
+ * buffer. */
SFXOpenAL::~SFXOpenAL()
{
- if (m_ok)
+ if (m_status!=SFX_UNKNOWN)
{
- alDeleteSources(1, &m_soundSource);
+ alDeleteSources(1, &m_sound_source);
}
- if (m_owns_buffer && m_soundBuffer != NULL)
+ if (m_owns_buffer && m_sound_buffer)
{
- m_soundBuffer->unload();
- delete m_soundBuffer;
+ m_sound_buffer->unload();
+ delete m_sound_buffer;
}
} // ~SFXOpenAL
//-----------------------------------------------------------------------------
-
+/** Initialises the sfx.
+ */
bool SFXOpenAL::init()
{
- alGenSources(1, &m_soundSource );
- if (!SFXManager::checkError("generating a source")) return false;
+ m_status = SFX_UNKNOWN;
- assert( alIsBuffer(m_soundBuffer->getBufferID()) );
- assert( alIsSource(m_soundSource) );
+ alGenSources(1, &m_sound_source );
+ if (!SFXManager::checkError("generating a source"))
+ return false;
- //std::cout << "Setting a source with buffer " << m_soundBuffer
- // << ", rolloff " << rolloff
- // << ", gain=" << m_defaultGain << ", positional="
- // << (positional ? "true" : "false") << std::endl;
+ assert( alIsBuffer(m_sound_buffer->getBufferID()) );
+ assert( alIsSource(m_sound_source) );
- alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer->getBufferID());
+ alSourcei (m_sound_source, AL_BUFFER, m_sound_buffer->getBufferID());
if (!SFXManager::checkError("attaching the buffer to the source"))
return false;
- alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0);
- alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0);
- alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0);
+ alSource3f(m_sound_source, AL_POSITION, 0.0, 0.0, 0.0);
+ alSource3f(m_sound_source, AL_VELOCITY, 0.0, 0.0, 0.0);
+ alSource3f(m_sound_source, AL_DIRECTION, 0.0, 0.0, 0.0);
- alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, m_soundBuffer->getRolloff());
- alSourcef (m_soundSource, AL_MAX_DISTANCE, m_soundBuffer->getMaxDist());
+ alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, m_sound_buffer->getRolloff());
+ alSourcef (m_sound_source, AL_MAX_DISTANCE, m_sound_buffer->getMaxDist());
if (m_gain < 0.0f)
{
- alSourcef (m_soundSource, AL_GAIN, m_defaultGain * m_master_gain);
+ alSourcef (m_sound_source, AL_GAIN, m_default_gain * m_master_gain);
}
else
{
- alSourcef (m_soundSource, AL_GAIN, m_gain * m_master_gain);
+ alSourcef (m_sound_source, AL_GAIN, m_gain * m_master_gain);
}
- if (m_positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
- else alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE);
+ if (m_positional) alSourcei (m_sound_source, AL_SOURCE_RELATIVE, AL_FALSE);
+ else alSourcei (m_sound_source, AL_SOURCE_RELATIVE, AL_TRUE);
- alSourcei(m_soundSource, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
+ alSourcei(m_sound_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
- m_ok = SFXManager::checkError("setting up the source");
+ if(!SFXManager::checkError("setting up the source"))
+ return false;
- return m_ok;
+ m_status = SFX_STOPPED;
+ return true;
} // init
+// ------------------------------------------------------------------------
+/** Updates the status of a playing sfx. If the sound has been played long
+ * enough, mark it to be finished. This avoid (a potentially costly)
+ * call to openal.
+ * \param dt Time step size.
+ */
+void SFXOpenAL::updatePlayingSFX(float dt)
+{
+ assert(m_status==SFX_PLAYING);
+ m_play_time += dt;
+ if(!m_loop && m_play_time > m_sound_buffer->getDuration())
+ m_status = SFX_STOPPED;
+} // updatePlayingSFX
+
//-----------------------------------------------------------------------------
-/** Changes the pitch of a sound effect.
+/** Queues up a change of the pitch of a sound effect to the sfx manager.
* \param factor Speedup/slowdown between 0.5 and 2.0
*/
-void SFXOpenAL::speed(float factor)
+void SFXOpenAL::setSpeed(float factor)
{
- if(!m_ok || isnan(factor)) return;
+ if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+ assert(!isnan(factor));
+ SFXManager::get()->queue(SFXManager::SFX_SPEED, this, factor);
+} // setSpeed
+
+//-----------------------------------------------------------------------------
+/** Changes the pitch of a sound effect. Executed from the sfx manager thread.
+ * \param factor Speedup/slowdown between 0.5 and 2.0
+ */
+void SFXOpenAL::reallySetSpeed(float factor)
+{
+ if(m_status==SFX_NOT_INITIALISED)
+ {
+ init();
+ if(m_status==SFX_UNKNOWN)
+ return;
+ }
//OpenAL only accepts pitches in the range of 0.5 to 2.0
if(factor > 2.0f)
@@ -138,23 +173,39 @@ void SFXOpenAL::speed(float factor)
{
factor = 0.5f;
}
- alSourcef(m_soundSource,AL_PITCH,factor);
- SFXManager::checkError("changing the speed");
-} // speed
+ alSourcef(m_sound_source,AL_PITCH,factor);
+} // reallySetSpeed
//-----------------------------------------------------------------------------
/** Changes the volume of a sound effect.
* \param gain Volume adjustment between 0.0 (mute) and 1.0 (full volume).
*/
-void SFXOpenAL::volume(float gain)
+void SFXOpenAL::setVolume(float gain)
{
- m_gain = m_defaultGain * gain;
+ if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+ assert(!isnan(gain)) ;
+ SFXManager::get()->queue(SFXManager::SFX_VOLUME, this, gain);
+} // setVolume
- if(!m_ok) return;
+//-----------------------------------------------------------------------------
+/** Changes the volume of a sound effect.
+ * \param gain Volume adjustment between 0.0 (mute) and 1.0 (full volume).
+ */
+void SFXOpenAL::reallySetVolume(float gain)
+{
+ m_gain = m_default_gain * gain;
- alSourcef(m_soundSource, AL_GAIN, m_gain * m_master_gain);
- SFXManager::checkError("setting volume");
-} // volume
+ if(m_status==SFX_UNKNOWN) return;
+
+ if(m_status==SFX_NOT_INITIALISED)
+ {
+ init();
+ if(m_status==SFX_UNKNOWN)
+ return;
+ }
+
+ alSourcef(m_sound_source, AL_GAIN, m_gain * m_master_gain);
+} // reallySetVolume
//-----------------------------------------------------------------------------
@@ -162,10 +213,17 @@ void SFXOpenAL::setMasterVolume(float gain)
{
m_master_gain = gain;
- if(!m_ok) return;
+ if(m_status==SFX_UNKNOWN) return;
+ if(m_status==SFX_NOT_INITIALISED)
+ {
+ init();
+ if(m_status==SFX_UNKNOWN)
+ return;
+ }
- alSourcef(m_soundSource, AL_GAIN,
- (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
+
+ alSourcef(m_sound_source, AL_GAIN,
+ (m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
SFXManager::checkError("setting volume");
} //setMasterVolume
@@ -174,55 +232,101 @@ void SFXOpenAL::setMasterVolume(float gain)
*/
void SFXOpenAL::setLoop(bool status)
{
- m_loop = status;
-
- if(!m_ok) return;
-
- alSourcei(m_soundSource, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
- SFXManager::checkError("looping");
-} // loop
+ if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+ SFXManager::get()->queue(SFXManager::SFX_LOOP, this, status ? 1.0f : 0.0f);
+} // setLoop
//-----------------------------------------------------------------------------
-/** Stops playing this sound effect.
+/** Loops this sound effect.
+ */
+void SFXOpenAL::reallySetLoop(bool status)
+{
+ if(m_status==SFX_NOT_INITIALISED)
+ {
+ init();
+ if(m_status==SFX_UNKNOWN)
+ return;
+ }
+ m_loop = status;
+
+ alSourcei(m_sound_source, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
+ SFXManager::checkError("looping");
+} // reallySetLoop
+
+//-----------------------------------------------------------------------------
+/** Queues a stop for this effect to the sound manager.
*/
void SFXOpenAL::stop()
{
- if(!m_ok) return;
-
- m_loop = false;
- alSourcei(m_soundSource, AL_LOOPING, AL_FALSE);
- alSourceStop(m_soundSource);
- SFXManager::checkError("stoping");
+ if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+ SFXManager::get()->queue(SFXManager::SFX_STOP, this);
} // stop
+//-----------------------------------------------------------------------------
+/** The sfx manager thread executes a stop for this sfx.
+ */
+void SFXOpenAL::reallyStopNow()
+{
+ if(m_status==SFX_PLAYING || m_status==SFX_PAUSED)
+ {
+ m_status = SFX_STOPPED;
+ m_loop = false;
+ alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
+ alSourceStop(m_sound_source);
+ SFXManager::checkError("stoping");
+ }
+} // reallyStopNow
+
+//-----------------------------------------------------------------------------
+/** Queues up a pause command for this sfx.
+ */
+void SFXOpenAL::pause()
+{
+ SFXManager::get()->queue(SFXManager::SFX_PAUSE, this);
+} // pause
+
//-----------------------------------------------------------------------------
/** Pauses a SFX that's currently played. Nothing happens it the effect is
* currently not being played.
*/
-void SFXOpenAL::pause()
+void SFXOpenAL::reallyPauseNow()
{
- if(!m_ok) return;
- alSourcePause(m_soundSource);
+ // Need to be tested again here, since this function can be called
+ // from pauseAll, and we have to make sure to only pause playing sfx.
+ if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
+ m_status = SFX_PAUSED;
+ alSourcePause(m_sound_source);
SFXManager::checkError("pausing");
-} // pause
+} // reallyPauseNow
+
+//-----------------------------------------------------------------------------
+/** Queues up a resume command for this sound effect.
+ */
+void SFXOpenAL::resume()
+{
+ if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
+ SFXManager::get()->queue(SFXManager::SFX_RESUME, this);
+} // resume
//-----------------------------------------------------------------------------
/** Resumes a sound effect.
*/
-void SFXOpenAL::resume()
+void SFXOpenAL::reallyResumeNow()
{
- if (!m_ok)
+ if(m_status==SFX_NOT_INITIALISED)
{
- // lazily create OpenAL source when needed
init();
-
- // creation of OpenAL source failed, giving up
- if (!m_ok) return;
+ if(m_status==SFX_UNKNOWN)
+ return;
}
- alSourcePlay(m_soundSource);
- SFXManager::checkError("resuming");
-} // resume
+ if(m_status==SFX_PAUSED)
+ {
+ alSourcePlay(m_sound_source);
+ SFXManager::checkError("resuming");
+ m_status = SFX_PLAYING;
+ }
+} // reallyResumeNow
//-----------------------------------------------------------------------------
/** This actually queues up the sfx in the sfx manager. It will be started
@@ -230,7 +334,18 @@ void SFXOpenAL::resume()
*/
void SFXOpenAL::play()
{
- SFXManager::get()->queue(this);
+ if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+
+ if(m_status==SFX_STOPPED)
+ m_play_time = 0.0f;
+
+ // Technically the sfx is only playing after the sfx thread starts it,
+ // but it is important to set this here since stk might decide to
+ // delete a sfx if it has finished playing (i.e. is in stopped state)
+ // - which can happen if the sfx thread had no time to actually start
+ // it yet.
+ m_status = SFX_PLAYING;
+ SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
} // play
//-----------------------------------------------------------------------------
@@ -239,16 +354,16 @@ void SFXOpenAL::play()
void SFXOpenAL::reallyPlayNow()
{
if (!SFXManager::get()->sfxAllowed()) return;
- if (!m_ok)
+ if (m_status==SFX_NOT_INITIALISED)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
- if (!m_ok) return;
+ if (m_status==SFX_UNKNOWN) return;
}
- alSourcePlay(m_soundSource);
+ alSourcePlay(m_sound_source);
SFXManager::checkError("playing");
} // reallyPlayNow
@@ -256,20 +371,31 @@ void SFXOpenAL::reallyPlayNow()
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
-void SFXOpenAL::position(const Vec3 &position)
+void SFXOpenAL::setPosition(const Vec3 &position)
{
- if(!UserConfigParams::m_sfx)
- return;
- if (!m_ok)
+ if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
+ SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
+
+} // setPosition
+
+//-----------------------------------------------------------------------------
+/** Sets the position where this sound effects is played.
+ * \param position Position of the sound effect.
+ */
+void SFXOpenAL::reallySetPosition(const Vec3 &position)
+{
+ if(m_status==SFX_NOT_INITIALISED)
{
- Log::warn("SFX", "Position called on non-ok SFX <%s>", m_soundBuffer->getFileName().c_str());
- return;
+ init();
+ if(m_status==SFX_UNKNOWN)
+ return;
}
+
if (!m_positional)
{
- // in multiplayer, all sounds are positional, so in this case don't bug users with
- // an error message if (race_manager->getNumLocalPlayers() > 1)
- // (note that 0 players is also possible, in cutscenes)
+ // in multiplayer, all sounds are positional, so in this case don't
+ // bug users with an error message if (note that 0 players is also
+ // possible, in cutscenes)
if (race_manager->getNumLocalPlayers() < 2)
{
Log::warn("SFX", "Position called on non-positional SFX");
@@ -277,39 +403,32 @@ void SFXOpenAL::position(const Vec3 &position)
return;
}
- alSource3f(m_soundSource, AL_POSITION,
- (float)position.getX(), (float)position.getY(), (float)position.getZ());
+ alSource3f(m_sound_source, AL_POSITION, (float)position.getX(),
+ (float)position.getY(), (float)position.getZ());
- if (SFXManager::get()->getListenerPos().distance(position) > m_soundBuffer->getMaxDist())
+ if (SFXManager::get()->getListenerPos().distance(position)
+ > m_sound_buffer->getMaxDist())
{
- alSourcef(m_soundSource, AL_GAIN, 0);
+ alSourcef(m_sound_source, AL_GAIN, 0);
}
else
{
- alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
+ alSourcef(m_sound_source, AL_GAIN,
+ (m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
SFXManager::checkError("positioning");
-} // position
+} // reallySetPosition
//-----------------------------------------------------------------------------
-/** Returns the status of this sound effect.
+/** Queues up a delete request for this object. This is necessary to avoid
+ * a crash if the sfx manager thread might be delayed and access this object
+ * after it was deleted.
*/
-SFXManager::SFXStatus SFXOpenAL::getStatus()
+void SFXOpenAL::deleteSFX()
{
- if(!m_ok) return SFXManager::SFX_UNKNOWN;
-
- int state = 0;
- alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
- switch(state)
- {
- case AL_STOPPED: return SFXManager::SFX_STOPPED;
- case AL_PLAYING: return SFXManager::SFX_PLAYING;
- case AL_PAUSED: return SFXManager::SFX_PAUSED;
- case AL_INITIAL: return SFXManager::SFX_INITIAL;
- default: return SFXManager::SFX_UNKNOWN;
- }
-} // getStatus
+ SFXManager::get()->queue(SFXManager::SFX_DELETE, this);
+} // deleteSFX
//-----------------------------------------------------------------------------
@@ -317,22 +436,23 @@ void SFXOpenAL::onSoundEnabledBack()
{
if (m_loop)
{
- if (!m_ok) init();
- if (m_ok)
+ if (m_status==SFX_NOT_INITIALISED) init();
+ if (m_status!=SFX_UNKNOWN)
{
- alSourcef(m_soundSource, AL_GAIN, 0);
+ alSourcef(m_sound_source, AL_GAIN, 0);
play();
pause();
- alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
+ alSourcef(m_sound_source, AL_GAIN,
+ (m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
}
-}
+} // onSoundEnabledBack
//-----------------------------------------------------------------------------
void SFXOpenAL::setRolloff(float rolloff)
{
- alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, rolloff);
+ alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff);
}
#endif //if HAVE_OGGVORBIS
diff --git a/src/audio/sfx_openal.hpp b/src/audio/sfx_openal.hpp
index 58a93eafb..f417fedbb 100644
--- a/src/audio/sfx_openal.hpp
+++ b/src/audio/sfx_openal.hpp
@@ -28,7 +28,6 @@
# include
#endif
#include "audio/sfx_base.hpp"
-#include "audio/sfx_manager.hpp"
#include "utils/leak_check.hpp"
/**
@@ -38,11 +37,22 @@
class SFXOpenAL : public SFXBase
{
private:
- SFXBuffer* m_soundBuffer; //!< Buffers hold sound data.
- ALuint m_soundSource; //!< Sources are points emitting sound.
- bool m_ok;
+ LEAK_CHECK()
+
+ /** Buffers hold sound data. */
+ SFXBuffer* m_sound_buffer;
+
+ /** Sources are points emitting sound. */
+ ALuint m_sound_source;
+
+ /** The status of this SFX. */
+ SFXStatus m_status;
+
+ /** If the sfx is positional. */
bool m_positional;
- float m_defaultGain;
+
+ /** Default gain value. */
+ float m_default_gain;
/** The OpenAL source contains this info, but if audio is disabled initially then
the sound source won't be created and we'll be left with no clue when enabling
@@ -59,33 +69,49 @@ private:
/** The master gain set in user preferences */
float m_master_gain;
+ /** If this sfx should also free the sound buffer. */
bool m_owns_buffer;
+ /** How long the sfx has been playing. */
+ float m_play_time;
+
public:
- SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
- bool owns_buffer = false);
- virtual ~SFXOpenAL();
+ SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
+ bool owns_buffer = false);
+ virtual ~SFXOpenAL();
- /** Late creation, if SFX was initially disabled */
- virtual bool init();
+ virtual void updatePlayingSFX(float dt);
+ virtual bool init();
+ virtual void play();
+ virtual void reallyPlayNow();
+ virtual void setLoop(bool status);
+ virtual void reallySetLoop(bool status);
+ virtual void stop();
+ virtual void reallyStopNow();
+ virtual void pause();
+ virtual void reallyPauseNow();
+ virtual void resume();
+ virtual void reallyResumeNow();
+ virtual void deleteSFX();
+ virtual void setSpeed(float factor);
+ virtual void reallySetSpeed(float factor);
+ virtual void setPosition(const Vec3 &position);
+ virtual void reallySetPosition(const Vec3 &p);
+ virtual void setVolume(float gain);
+ virtual void reallySetVolume(float gain);
+ virtual void setMasterVolume(float gain);
+ virtual void onSoundEnabledBack();
+ virtual void setRolloff(float rolloff);
+ // ------------------------------------------------------------------------
+ /** Returns if this sfx is looped or not. */
+ virtual bool isLooped() { return m_loop; }
+ // ------------------------------------------------------------------------
+ /** Returns the status of this sfx. */
+ virtual SFXStatus getStatus() { return m_status; }
- virtual void play();
- virtual void reallyPlayNow();
- virtual void setLoop(bool status);
- virtual void stop();
- virtual void pause();
- virtual void resume();
- virtual void speed(float factor);
- virtual void position(const Vec3 &position);
- virtual void volume(float gain);
- virtual void setMasterVolume(float gain);
- virtual SFXManager::SFXStatus getStatus();
- virtual void onSoundEnabledBack();
- virtual void setRolloff(float rolloff);
-
- virtual const SFXBuffer* getBuffer() const { return m_soundBuffer; }
-
- LEAK_CHECK()
+ // ------------------------------------------------------------------------
+ /** Returns the buffer associated with this sfx. */
+ virtual const SFXBuffer* getBuffer() const { return m_sound_buffer; }
}; // SFXOpenAL
diff --git a/src/config/device_config.cpp b/src/config/device_config.cpp
index 488550389..96a671899 100644
--- a/src/config/device_config.cpp
+++ b/src/config/device_config.cpp
@@ -83,6 +83,10 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
returnString += id;
break;
+ case Input::IT_NONE:
+ returnString += "none";
+ break;
+
default:
assert(false);
returnString += type;
diff --git a/src/config/hardware_stats.cpp b/src/config/hardware_stats.cpp
index 0770c2fe2..275cb71a0 100644
--- a/src/config/hardware_stats.cpp
+++ b/src/config/hardware_stats.cpp
@@ -23,15 +23,31 @@
#include "graphics/irr_driver.hpp"
#include "online/http_request.hpp"
#include "utils/random_generator.hpp"
-#include "utils/string_utils.hpp"
#ifdef __APPLE__
# include
#endif
+#include
+#include
+#include
+#include
+#ifndef WIN32
+# include // To get BSD macro
+# include
+#endif
+#include
+
+
namespace HardwareStats
{
+ namespace Private
+ {
+ /** Stores the OS version, e.g. "Windows 7", or "Fedora 21". */
+ static std::string m_os_version;
+ } // namespace Private
+ using namespace Private;
// ----------------------------------------------------------------------------
/** Returns the amount of RAM in MB.
@@ -40,7 +56,7 @@ namespace HardwareStats
int getRAM()
{
#ifdef __linux__
- const uint64_t memory_size = (uint64_t)sysconf(_SC_PHYS_PAGES)
+ const uint64_t memory_size = (uint64_t)sysconf(_SC_PHYS_PAGES)
* sysconf(_SC_PAGESIZE);
return int(memory_size / (1024*1024));
#endif
@@ -102,6 +118,138 @@ int getNumProcessors()
return 0;
} // getNumProcessors
+// ----------------------------------------------------------------------------
+/** Tries opening and parsing the specified release file in /etc to find
+ * information about the distro used.
+ * \param filename Full path of the file to open.
+ * \return True if file could be read and valid information was paresed,
+ * false otherwise.
+ */
+bool readEtcReleaseFile(const std::string &filename)
+{
+ std::ifstream in(filename);
+ std::string s, distro, version;
+ while( (distro.empty() || version.empty()) &&
+ std::getline(in, s) )
+ {
+ std::vector l = StringUtils::split(s, '=');
+ if(l.size()==0) continue;
+ if (l[0]=="NAME" ) distro = l[1];
+ else if(l[0]=="VERSION_ID") version = l[1];
+ }
+ if(!distro.empty() && !version.empty())
+ {
+ distro = StringUtils::replace(distro, "\"", "");
+ version = StringUtils::replace(version, "\"", "");
+ m_os_version = distro + " " + version;
+ return true;
+ }
+ return false;
+} // readEtcReleaseFile
+
+// ----------------------------------------------------------------------------
+/** Identify more details about the OS, e.g. on linux which distro
+ * and which verison; on windows the version number.
+ * \param json Json data structure to store the os info in.
+ */
+void determineOSVersion()
+{
+ std::string version, distro;
+
+#ifdef __linux__
+ // First try the standard /etc/os-release. Then check for older versions
+ // e.g. /etc/fedora-release, /etc/SuSE-release, /etc/redhat-release
+ if(readEtcReleaseFile("/etc/os-release")) return;
+
+ std::set file_list;
+ file_manager->listFiles(file_list, "./", true);
+ for(std::set::iterator i = file_list.begin();
+ i != file_list.end(); i++)
+ {
+ // Only try reading /etc/*-release files
+ if(StringUtils::hasSuffix(*i, "-release"))
+ if (readEtcReleaseFile(*i)) return;
+ }
+ // Fallback in case that we can't find any valid information in /etc/*release
+ struct utsname u;
+ if (uname(&u))
+ {
+ m_os_version = "Linux unknown";
+ return;
+ }
+ // Ignore data after "-", since it could identify a system (self compiled
+ // kernels).
+ std::vector l = StringUtils::split(std::string(u.release),'-');
+ m_os_version = std::string(u.sysname) + " " + l[0];
+
+#endif
+
+#ifdef BSD
+ struct utsname u;
+ if (uname(&u))
+ {
+ m_os_version = "BSD unknown";
+ return;
+ }
+ // Ignore data after "-", since it could identify a system (self compiled
+ // kernels).
+ std::vector l = StringUtils::split(std::string(u.release),'-');
+ m_os_version = std::string(u.sysname) + " " + l[0];
+#endif
+
+#ifdef WIN32
+ // (C) 2014 by Wildfire Games (0 A.D.), ported by Joerg Henrichs.
+
+ HKEY hKey;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
+ KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+ {
+ m_os_version = "windows-unknown";
+ return;
+ }
+ char windows_version_string[20];
+ DWORD size = sizeof(windows_version_string);
+ RegQueryValueEx(hKey, "CurrentVersion", 0, 0, (LPBYTE)windows_version_string, &size);
+ unsigned major = 0, minor = 0;
+
+ std::stringstream sstr(windows_version_string);
+ sstr >> major;
+ if (sstr.peek() == '.')
+ sstr.ignore();
+ sstr >> minor;
+
+ int windows_version = (major << 8) | minor;
+ RegCloseKey(hKey);
+
+ switch(windows_version)
+ {
+ case 0x0500: m_os_version="Windows 2000"; break;
+ case 0x0501: m_os_version="Windows XP"; break;
+ case 0x0502: m_os_version="Windows XP64"; break;
+ case 0x0600: m_os_version="Windows Vista"; break;
+ case 0x0601: m_os_version="Windows 7"; break;
+ case 0x0602: m_os_version="Windows 8"; break;
+ default: {
+ m_os_version = StringUtils::insertValues("Windows %d",
+ windows_version);
+ break;
+ }
+ } // switch
+
+#endif
+} // determineOSVersion
+
+// ----------------------------------------------------------------------------
+/** Returns the OS version, e.g.: "Windows 7", or "Fedora 21".
+ */
+const std::string& getOSVersion()
+{
+ if(m_os_version.empty())
+ determineOSVersion();
+ return m_os_version;
+} // getOSVersion
+
// ----------------------------------------------------------------------------
/** If the configuration of this installation has not been reported for the
* current version, collect the hardware statistics and send it to STK's
@@ -144,10 +292,12 @@ void reportHardwareStats()
json.add("build_debug", 1);
#endif
+ json.add("os_version", getOSVersion());
+
unsigned int ogl_version = irr_driver->getGLSLVersion();
unsigned int major = ogl_version/100;
unsigned int minor = ogl_version - 100*major;
- std::string version =
+ std::string version =
StringUtils::insertValues("%d.%d", major, minor);
json.add("GL_SHADING_LANGUAGE_VERSION", version);
@@ -166,7 +316,7 @@ void reportHardwareStats()
else if(StringUtils::startsWith(card_name, "S3 Graphics"))
card_name="S3";
json.add("gfx_card", card_name+" "+renderer);
-
+
json.add("video_xres", UserConfigParams::m_width );
json.add("video_yres", UserConfigParams::m_height);
@@ -195,14 +345,14 @@ void reportHardwareStats()
int m_version;
public:
HWReportRequest(int version) : Online::HTTPRequest(/*manage memory*/true, 1)
- ,m_version(version)
+ , m_version(version)
{}
// --------------------------------------------------------------------
- /** Callback after the request has been executed.
+ /** Callback after the request has been executed.
*/
virtual void callback()
{
- // If the request contains incorrect data, it will not have a
+ // If the request contains incorrect data, it will not have a
// download error, but return an error string as return value:
if(hadDownloadError() || getData()=="Bad Request (400)
")
{
diff --git a/src/config/hardware_stats.hpp b/src/config/hardware_stats.hpp
index f49f73ce5..4c5ef321f 100644
--- a/src/config/hardware_stats.hpp
+++ b/src/config/hardware_stats.hpp
@@ -25,11 +25,14 @@
#include "utils/no_copy.hpp"
#include "utils/string_utils.hpp"
+
namespace HardwareStats
{
+ /** A class to manage json data. */
class Json : public NoCopy
{
private:
+ /** The accumulated json data. */
std::string m_data;
public:
/** Constructor. */
@@ -78,6 +81,7 @@ namespace HardwareStats
// ========================================================================
void reportHardwareStats();
+ const std::string& getOSVersion();
}; // HardwareStats
#endif
diff --git a/src/config/player_manager.cpp b/src/config/player_manager.cpp
index d138b8b18..09dc473ce 100644
--- a/src/config/player_manager.cpp
+++ b/src/config/player_manager.cpp
@@ -170,7 +170,11 @@ PlayerManager::~PlayerManager()
for_var_in(PlayerProfile*, player, m_all_players)
{
if(!player->rememberPassword())
- player->clearSession();
+ {
+ // Don't let the player trigger a save, since it
+ // will be done below anyway.
+ player->clearSession(/*save*/false);
+ }
}
save();
diff --git a/src/config/player_profile.cpp b/src/config/player_profile.cpp
index ef75c8637..04624f20c 100644
--- a/src/config/player_profile.cpp
+++ b/src/config/player_profile.cpp
@@ -244,12 +244,13 @@ void PlayerProfile::saveSession(int user_id, const std::string &token)
// ------------------------------------------------------------------------
/** Unsets any saved session data. */
-void PlayerProfile::clearSession()
+void PlayerProfile::clearSession(bool save)
{
m_saved_session = false;
m_saved_user_id = 0;
m_saved_token = "";
- PlayerManager::get()->save();
+ if(save)
+ PlayerManager::get()->save();
} // clearSession
//------------------------------------------------------------------------------
diff --git a/src/config/player_profile.hpp b/src/config/player_profile.hpp
index 9b6fb89b6..b38b00a2e 100644
--- a/src/config/player_profile.hpp
+++ b/src/config/player_profile.hpp
@@ -129,7 +129,7 @@ public:
bool operator<(const PlayerProfile &other);
void raceFinished();
void saveSession(int user_id, const std::string &token);
- void clearSession();
+ void clearSession(bool save=true);
void addIcon();
/** Abstract virtual classes, to be implemented by the OnlinePlayer. */
diff --git a/src/config/saved_grand_prix.cpp b/src/config/saved_grand_prix.cpp
index 3805457da..8f01643a6 100644
--- a/src/config/saved_grand_prix.cpp
+++ b/src/config/saved_grand_prix.cpp
@@ -71,7 +71,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
const std::vector &kart_list)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
- m_player_id(player_id),
+ m_player_id(player_id, "player_id", &m_savedgp_group),
m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group),
m_difficulty((int)difficulty,"difficulty", &m_savedgp_group),
m_player_karts(player_karts,"player_karts", &m_savedgp_group),
@@ -94,13 +94,14 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
- m_player_id(0),
+ m_player_id(0, "player_id", &m_savedgp_group),
m_gp_id("-", "gp_id", &m_savedgp_group),
m_difficulty(0,"difficulty", &m_savedgp_group),
m_player_karts(0,"player_karts", &m_savedgp_group),
m_next_track(0,"last_track", &m_savedgp_group)
{
//m_player_group.findYourDataInAChildOf(node);
+ m_player_id.findYourDataInAnAttributeOf(node);
m_gp_id.findYourDataInAnAttributeOf(node);
m_difficulty.findYourDataInAnAttributeOf(node);
m_player_karts.findYourDataInAnAttributeOf(node);
diff --git a/src/config/saved_grand_prix.hpp b/src/config/saved_grand_prix.hpp
index e8aa32217..840da10c7 100644
--- a/src/config/saved_grand_prix.hpp
+++ b/src/config/saved_grand_prix.hpp
@@ -60,7 +60,7 @@ protected:
* WARNING : m_savedgp_group has to be declared before the other userconfigparams!
*/
GroupUserConfigParam m_savedgp_group;
- unsigned int m_player_id;
+ IntUserConfigParam m_player_id;
/** Identifier of this GP. */
StringUserConfigParam m_gp_id;
@@ -145,6 +145,7 @@ public:
for (unsigned int n=0; ngetGPID() == gpid) &&
(gp->getPlayerID() == player) &&
(gp->getDifficulty() == difficulty) &&
diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp
index fb5c742aa..a6c8b1988 100644
--- a/src/config/user_config.cpp
+++ b/src/config/user_config.cpp
@@ -140,8 +140,7 @@ void GroupUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
- //std::cerr << "/!\\ User Config : Couldn't find parameter group "
- // << paramName << std::endl;
+ //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
@@ -271,8 +270,7 @@ void ListUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
- //std::cerr << "/!\\ User Config : Couldn't find parameter group "
- // << paramName << std::endl;
+ //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
@@ -374,12 +372,12 @@ void IntUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if(child == NULL)
{
- //std::cout << "Couldn't find int parameter " << paramName << std::endl;
+ //Log::error("UserConfigParam", "Couldn't find int parameter %s", m_param_name.c_str());
return;
}
child->get( "value", &m_value );
- //std::cout << "read int " << paramName << ", value=" << value << std::endl;
+ //Log::info("UserConfigParam", "Read int %s ,value = %d", m_param_name.c_str(), value);
} // findYourDataInAChildOf
// ----------------------------------------------------------------------------
@@ -442,7 +440,7 @@ void TimeUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if(child == NULL)
{
- //std::cout << "Couldn't find int parameter " << paramName <colorvbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
+
+ glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
+ glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
+
+ UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(static_cast(texture)->getOpenGLTextureName()));
+ UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
+ core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
+ core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glGetError();
+}
+
+static
+void drawTexQuad(GLuint texture, float width, float height,
+float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
+float tex_width, float tex_height)
+{
+ glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
+ glBindVertexArray(SharedObject::UIVAO);
+
+ UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector(texture));
+ UIShader::TextureRectShader::getInstance()->setUniforms(
+ core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
+ core::vector2df(tex_center_pos_x, tex_center_pos_y),
+ core::vector2df(tex_width, tex_height));
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glGetError();
+}
+
+static void
+getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
+const core::rect& destRect,
+const core::rect& sourceRect,
+float &width, float &height,
+float ¢er_pos_x, float ¢er_pos_y,
+float &tex_width, float &tex_height,
+float &tex_center_pos_x, float &tex_center_pos_y
+)
+{
+ core::dimension2d frame_size =
+ irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
+ const int screen_w = frame_size.Width;
+ const int screen_h = frame_size.Height;
+ center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
+ center_pos_x /= screen_w;
+ center_pos_x -= 1.;
+ center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
+ center_pos_y /= screen_h;
+ center_pos_y = float(1.f - center_pos_y);
+ width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
+ width /= screen_w;
+ height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
+ height /= screen_h;
+
+ tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
+ tex_center_pos_x /= texture_width * 2.f;
+ tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
+ tex_center_pos_y /= texture_height * 2.f;
+ tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
+ tex_width /= texture_width * 2.f;
+ tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
+ tex_height /= texture_height * 2.f;
+
+ if (textureisRTT)
+ tex_height = -tex_height;
+
+ const f32 invW = 1.f / static_cast(texture_width);
+ const f32 invH = 1.f / static_cast(texture_height);
+ const core::rect tcoords(
+ sourceRect.UpperLeftCorner.X * invW,
+ sourceRect.UpperLeftCorner.Y * invH,
+ sourceRect.LowerRightCorner.X * invW,
+ sourceRect.LowerRightCorner.Y *invH);
+}
+
+void draw2DImage(const video::ITexture* texture, const core::rect& destRect,
+ const core::rect& sourceRect, const core::rect* clipRect,
+ const video::SColor &colors, bool useAlphaChannelOfTexture)
+{
+ if (!irr_driver->isGLSL()) {
+ video::SColor duplicatedArray[4] = {
+ colors, colors, colors, colors
+ };
+ draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
+ return;
+ }
+
+ float width, height,
+ center_pos_x, center_pos_y,
+ tex_width, tex_height,
+ tex_center_pos_x, tex_center_pos_y;
+
+ getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
+ destRect, sourceRect, width, height, center_pos_x, center_pos_y,
+ tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
+
+ if (useAlphaChannelOfTexture)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else
+ {
+ glDisable(GL_BLEND);
+ }
+ if (clipRect)
+ {
+ if (!clipRect->isValid())
+ return;
+
+ glEnable(GL_SCISSOR_TEST);
+ const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
+ glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
+ clipRect->getWidth(), clipRect->getHeight());
+ }
+
+ glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
+ glBindVertexArray(SharedObject::UIVAO);
+
+ UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(static_cast(texture)->getOpenGLTextureName()));
+ UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
+ core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ if (clipRect)
+ glDisable(GL_SCISSOR_TEST);
+ glUseProgram(0);
+
+ glGetError();
+}
+
+void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
+ const core::rect& destRect,
+ const core::rect& sourceRect, const core::rect* clipRect,
+ const video::SColor &colors, bool useAlphaChannelOfTexture)
+{
+ if (useAlphaChannelOfTexture)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ float width, height,
+ center_pos_x, center_pos_y,
+ tex_width, tex_height,
+ tex_center_pos_x, tex_center_pos_y;
+
+ getSize((int)texture_w, (int)texture_h, true,
+ destRect, sourceRect, width, height, center_pos_x, center_pos_y,
+ tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
+
+ glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
+ glBindVertexArray(SharedObject::UIVAO);
+
+ UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(texture));
+ UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
+ core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
+ core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
+ colors);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void draw2DImage(const video::ITexture* texture, const core::rect& destRect,
+ const core::rect& sourceRect, const core::rect* clipRect,
+ const video::SColor* const colors, bool useAlphaChannelOfTexture)
+{
+ if (!irr_driver->isGLSL())
+ {
+ irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
+ return;
+ }
+
+ float width, height,
+ center_pos_x, center_pos_y,
+ tex_width, tex_height,
+ tex_center_pos_x, tex_center_pos_y;
+
+ getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
+ destRect, sourceRect, width, height, center_pos_x, center_pos_y,
+ tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
+
+ if (useAlphaChannelOfTexture)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else
+ {
+ glDisable(GL_BLEND);
+ }
+ if (clipRect)
+ {
+ if (!clipRect->isValid())
+ return;
+
+ glEnable(GL_SCISSOR_TEST);
+ const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
+ glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
+ clipRect->getWidth(), clipRect->getHeight());
+ }
+ if (colors)
+ drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
+ tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
+ else
+ drawTexQuad(static_cast(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
+ tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
+ if (clipRect)
+ glDisable(GL_SCISSOR_TEST);
+ glUseProgram(0);
+
+ glGetError();
+}
+
+void draw2DVertexPrimitiveList(video::ITexture *tex, const void* vertices,
+ u32 vertexCount, const void* indexList, u32 primitiveCount,
+ video::E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, video::E_INDEX_TYPE iType)
+{
+ if (!irr_driver->isGLSL())
+ {
+ irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
+ return;
+ }
+ GLuint tmpvao, tmpvbo, tmpibo;
+ primitiveCount += 2;
+ glGenVertexArrays(1, &tmpvao);
+ glBindVertexArray(tmpvao);
+ glGenBuffers(1, &tmpvbo);
+ glBindBuffer(GL_ARRAY_BUFFER, tmpvbo);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * getVertexPitchFromType(vType), vertices, GL_STREAM_DRAW);
+ glGenBuffers(1, &tmpibo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tmpibo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, primitiveCount * sizeof(u16), indexList, GL_STREAM_DRAW);
+
+ VertexUtils::bindVertexArrayAttrib(vType);
+
+ glUseProgram(UIShader::Primitive2DList::getInstance()->Program);
+ UIShader::Primitive2DList::getInstance()->setUniforms();
+ const video::SOverrideMaterial &m = irr_driver->getVideoDriver()->getOverrideMaterial();
+ compressTexture(tex, false);
+ UIShader::Primitive2DList::getInstance()->SetTextureUnits({ getTextureGLuint(tex) });
+ glDrawElements(GL_TRIANGLE_FAN, primitiveCount, GL_UNSIGNED_SHORT, 0);
+
+ glDeleteVertexArrays(1, &tmpvao);
+ glDeleteBuffers(1, &tmpvbo);
+ glDeleteBuffers(1, &tmpibo);
+
+}
+
+void GL32_draw2DRectangle(video::SColor color, const core::rect& position,
+ const core::rect* clip)
+{
+
+ if (!irr_driver->isGLSL())
+ {
+ irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
+ return;
+ }
+
+ core::dimension2d frame_size =
+ irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
+ const int screen_w = frame_size.Width;
+ const int screen_h = frame_size.Height;
+ float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
+ center_pos_x /= screen_w;
+ center_pos_x -= 1;
+ float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
+ center_pos_y /= screen_h;
+ center_pos_y = 1 - center_pos_y;
+ float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
+ width /= screen_w;
+ float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
+ height /= screen_h;
+
+ if (color.getAlpha() < 255)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else
+ {
+ glDisable(GL_BLEND);
+ }
+
+ if (clip)
+ {
+ if (!clip->isValid())
+ return;
+
+ glEnable(GL_SCISSOR_TEST);
+ const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
+ glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
+ clip->getWidth(), clip->getHeight());
+ }
+
+ glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
+ glBindVertexArray(SharedObject::UIVAO);
+ UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ if (clip)
+ glDisable(GL_SCISSOR_TEST);
+ glUseProgram(0);
+
+ glGetError();
+}
diff --git a/src/graphics/2dutils.hpp b/src/graphics/2dutils.hpp
new file mode 100644
index 000000000..47b0b1ef5
--- /dev/null
+++ b/src/graphics/2dutils.hpp
@@ -0,0 +1,33 @@
+#ifndef UTILS2D_HPP
+#define UTILS2D_HPP
+
+#include "gl_headers.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
+ const irr::core::rect& destRect,
+ const irr::core::rect& sourceRect, const irr::core::rect* clipRect,
+ const irr::video::SColor &colors, bool useAlphaChannelOfTexture);
+
+void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect& destRect,
+ const irr::core::rect& sourceRect, const irr::core::rect* clipRect,
+ const irr::video::SColor &color, bool useAlphaChannelOfTexture);
+
+void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect& destRect,
+ const irr::core::rect& sourceRect, const irr::core::rect* clipRect,
+ const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
+
+void draw2DVertexPrimitiveList(irr::video::ITexture *t, const void* vertices,
+ irr::u32 vertexCount, const void* indexList, irr::u32 primitiveCount,
+ irr::video::E_VERTEX_TYPE vType = irr::video::EVT_STANDARD, irr::scene::E_PRIMITIVE_TYPE pType = irr::scene::EPT_TRIANGLES, irr::video::E_INDEX_TYPE iType = irr::video::EIT_16BIT);
+
+void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect& position,
+ const irr::core::rect* clip = 0);
+
+#endif
\ No newline at end of file
diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp
index 446f308c1..5195773dd 100644
--- a/src/graphics/camera.cpp
+++ b/src/graphics/camera.cpp
@@ -372,7 +372,9 @@ void Camera::smoothMoveCamera(float dt)
if (race_manager->getNumLocalPlayers() < 2)
{
- SFXManager::get()->positionListener(current_position, current_target - current_position);
+ SFXManager::get()->positionListener(current_position,
+ current_target - current_position,
+ Vec3(0,1,0));
}
} // smoothMoveCamera
@@ -578,7 +580,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(m_camera->getPosition(),
- wanted_target - m_camera->getPosition());
+ wanted_target - m_camera->getPosition(),
+ Vec3(0, 1, 0));
}
}
diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp
index 3885c133b..e13454bef 100644
--- a/src/graphics/glwrap.cpp
+++ b/src/graphics/glwrap.cpp
@@ -6,9 +6,6 @@
#include "utils/profiler.hpp"
#include "utils/cpp2011.hpp"
-
-#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
-
#include
#include
#include
@@ -122,159 +119,6 @@ void initGL()
#endif
}
-static std::string LoadHeader()
-{
- std::string result;
- std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
-
- if (Stream.is_open())
- {
- std::string Line = "";
- while (getline(Stream, Line))
- result += "\n" + Line;
- Stream.close();
- }
-
- return result;
-}
-
-// Mostly from shader tutorial
-GLuint LoadShader(const char * file, unsigned type)
-{
- GLuint Id = glCreateShader(type);
- char versionString[20];
- sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
- std::string Code = versionString;
- if (irr_driver->hasVSLayerExtension())
- Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
- if (UserConfigParams::m_azdo)
- Code += "#extension GL_ARB_bindless_texture : enable\n";
- else
- {
- Code += "#extension GL_ARB_bindless_texture : disable\n";
- Code += "#undef GL_ARB_bindless_texture\n";
- }
- std::ifstream Stream(file, std::ios::in);
- Code += "//" + std::string(file) + "\n";
- if (irr_driver->needUBOWorkaround())
- Code += "#define UBO_DISABLED\n";
- if (irr_driver->hasVSLayerExtension())
- Code += "#define VSLayer\n";
- if (irr_driver->needsRGBBindlessWorkaround())
- Code += "#define SRGBBindlessFix\n";
- Code += LoadHeader();
- if (Stream.is_open())
- {
- std::string Line = "";
- while (getline(Stream, Line))
- Code += "\n" + Line;
- Stream.close();
- }
- GLint Result = GL_FALSE;
- int InfoLogLength;
- Log::info("GLWrap", "Compiling shader : %s", file);
- char const * SourcePointer = Code.c_str();
- int length = (int)strlen(SourcePointer);
- glShaderSource(Id, 1, &SourcePointer, &length);
- glCompileShader(Id);
-
- glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
- if (Result == GL_FALSE)
- {
- Log::error("GLWrap", "Error in shader %s", file);
- glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
- if(InfoLogLength<0)
- InfoLogLength = 1024;
- char *ErrorMessage = new char[InfoLogLength];
- ErrorMessage[0]=0;
- glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
- Log::error("GLWrap", ErrorMessage);
- delete[] ErrorMessage;
- }
-
- glGetError();
-
- return Id;
-}
-
-void setAttribute(AttributeType Tp, GLuint ProgramID)
-{
- switch (Tp)
- {
- case OBJECT:
- glBindAttribLocation(ProgramID, 0, "Position");
- glBindAttribLocation(ProgramID, 1, "Normal");
- glBindAttribLocation(ProgramID, 2, "Color");
- glBindAttribLocation(ProgramID, 3, "Texcoord");
- glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
- glBindAttribLocation(ProgramID, 5, "Tangent");
- glBindAttribLocation(ProgramID, 6, "Bitangent");
- glBindAttribLocation(ProgramID, 7, "Origin");
- glBindAttribLocation(ProgramID, 8, "Orientation");
- glBindAttribLocation(ProgramID, 9, "Scale");
- break;
- case PARTICLES_SIM:
- glBindAttribLocation(ProgramID, 0, "particle_position");
- glBindAttribLocation(ProgramID, 1, "lifetime");
- glBindAttribLocation(ProgramID, 2, "particle_velocity");
- glBindAttribLocation(ProgramID, 3, "size");
- glBindAttribLocation(ProgramID, 4, "particle_position_initial");
- glBindAttribLocation(ProgramID, 5, "lifetime_initial");
- glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
- glBindAttribLocation(ProgramID, 7, "size_initial");
- break;
- case PARTICLES_RENDERING:
- glBindAttribLocation(ProgramID, 1, "lifetime");
- glBindAttribLocation(ProgramID, 2, "size");
- glBindAttribLocation(ProgramID, 4, "quadcorner");
- glBindAttribLocation(ProgramID, 5, "rotationvec");
- glBindAttribLocation(ProgramID, 6, "anglespeed");
- break;
- }
-}
-
-GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
-{
- GLuint Program = glCreateProgram();
- loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
- if (irr_driver->getGLSLVersion() < 330)
- setAttribute(PARTICLES_SIM, Program);
- glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
- glLinkProgram(Program);
-
- GLint Result = GL_FALSE;
- int InfoLogLength;
- glGetProgramiv(Program, GL_LINK_STATUS, &Result);
- if (Result == GL_FALSE)
- {
- glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
- char *ErrorMessage = new char[InfoLogLength];
- glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
- Log::error("GLWrap", ErrorMessage);
- delete[] ErrorMessage;
- }
-
- glGetError();
-
- return Program;
-}
-
-void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
-{
- glActiveTexture(GL_TEXTURE0 + TextureUnit);
- glBindTexture(GL_TEXTURE_2D, TextureId);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- int aniso = UserConfigParams::m_anisotropic;
- if (aniso == 0) aniso = 1;
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, allowAF ? (float)aniso : 1.0f);
-
- glGetError();
-}
-
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
{
if (!UserConfigParams::m_profiler_enabled) return;
@@ -417,305 +261,7 @@ void draw3DLine(const core::vector3df& start,
glGetError();
}
-static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
- float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
- float tex_width, float tex_height)
-{
- unsigned colors[] = {
- col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
- col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
- col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
- col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
- };
-
- glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
-
- glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
- glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
-
- UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(static_cast(texture)->getOpenGLTextureName()));
- UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
- core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
- core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glGetError();
-}
-
-static
-void drawTexQuad(GLuint texture, float width, float height,
- float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
- float tex_width, float tex_height)
-{
- glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
- glBindVertexArray(SharedObject::UIVAO);
-
- UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector(texture));
- UIShader::TextureRectShader::getInstance()->setUniforms(
- core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
- core::vector2df(tex_center_pos_x, tex_center_pos_y),
- core::vector2df(tex_width, tex_height));
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glGetError();
-}
-
-static void
-getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
- const core::rect& destRect,
- const core::rect& sourceRect,
- float &width, float &height,
- float ¢er_pos_x, float ¢er_pos_y,
- float &tex_width, float &tex_height,
- float &tex_center_pos_x, float &tex_center_pos_y
- )
-{
- core::dimension2d frame_size =
- irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
- const int screen_w = frame_size.Width;
- const int screen_h = frame_size.Height;
- center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
- center_pos_x /= screen_w;
- center_pos_x -= 1.;
- center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
- center_pos_y /= screen_h;
- center_pos_y = float(1.f - center_pos_y);
- width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
- width /= screen_w;
- height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
- height /= screen_h;
-
- tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
- tex_center_pos_x /= texture_width * 2.f;
- tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
- tex_center_pos_y /= texture_height * 2.f;
- tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
- tex_width /= texture_width * 2.f;
- tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
- tex_height /= texture_height * 2.f;
-
- if (textureisRTT)
- tex_height = -tex_height;
-
- const f32 invW = 1.f / static_cast(texture_width);
- const f32 invH = 1.f / static_cast(texture_height);
- const core::rect tcoords(
- sourceRect.UpperLeftCorner.X * invW,
- sourceRect.UpperLeftCorner.Y * invH,
- sourceRect.LowerRightCorner.X * invW,
- sourceRect.LowerRightCorner.Y *invH);
-}
-
-void draw2DImage(const video::ITexture* texture, const core::rect& destRect,
- const core::rect& sourceRect, const core::rect* clipRect,
- const video::SColor &colors, bool useAlphaChannelOfTexture)
-{
- if (!irr_driver->isGLSL()) {
- video::SColor duplicatedArray[4] = {
- colors, colors, colors, colors
- };
- draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
- return;
- }
-
- float width, height,
- center_pos_x, center_pos_y,
- tex_width, tex_height,
- tex_center_pos_x, tex_center_pos_y;
-
- getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
- destRect, sourceRect, width, height, center_pos_x, center_pos_y,
- tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
-
- if (useAlphaChannelOfTexture)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- {
- glDisable(GL_BLEND);
- }
- if (clipRect)
- {
- if (!clipRect->isValid())
- return;
-
- glEnable(GL_SCISSOR_TEST);
- const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
- glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
- clipRect->getWidth(), clipRect->getHeight());
- }
-
- glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
- glBindVertexArray(SharedObject::UIVAO);
-
- UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(static_cast(texture)->getOpenGLTextureName()));
- UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
- core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- if (clipRect)
- glDisable(GL_SCISSOR_TEST);
- glUseProgram(0);
-
- glGetError();
-}
-
-void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
- const core::rect& destRect,
- const core::rect& sourceRect, const core::rect* clipRect,
- const video::SColor &colors, bool useAlphaChannelOfTexture)
-{
- if (useAlphaChannelOfTexture)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- float width, height,
- center_pos_x, center_pos_y,
- tex_width, tex_height,
- tex_center_pos_x, tex_center_pos_y;
-
- getSize((int)texture_w, (int)texture_h, true,
- destRect, sourceRect, width, height, center_pos_x, center_pos_y,
- tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
-
- glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
- glBindVertexArray(SharedObject::UIVAO);
-
- UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector(texture));
- UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
- core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
- core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
- colors);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void draw2DImage(const video::ITexture* texture, const core::rect& destRect,
- const core::rect& sourceRect, const core::rect* clipRect,
- const video::SColor* const colors, bool useAlphaChannelOfTexture)
-{
- if (!irr_driver->isGLSL())
- {
- irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
- return;
- }
-
- float width, height,
- center_pos_x, center_pos_y,
- tex_width, tex_height,
- tex_center_pos_x, tex_center_pos_y;
-
- getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
- destRect, sourceRect, width, height, center_pos_x, center_pos_y,
- tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
-
- if (useAlphaChannelOfTexture)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- {
- glDisable(GL_BLEND);
- }
- if (clipRect)
- {
- if (!clipRect->isValid())
- return;
-
- glEnable(GL_SCISSOR_TEST);
- const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
- glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
- clipRect->getWidth(), clipRect->getHeight());
- }
- if (colors)
- drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
- tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
- else
- drawTexQuad(static_cast(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
- tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
- if (clipRect)
- glDisable(GL_SCISSOR_TEST);
- glUseProgram(0);
-
- glGetError();
-}
-
-void GL32_draw2DRectangle(video::SColor color, const core::rect& position,
- const core::rect* clip)
-{
-
- if (!irr_driver->isGLSL())
- {
- irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
- return;
- }
-
- core::dimension2d frame_size =
- irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
- const int screen_w = frame_size.Width;
- const int screen_h = frame_size.Height;
- float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
- center_pos_x /= screen_w;
- center_pos_x -= 1;
- float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
- center_pos_y /= screen_h;
- center_pos_y = 1 - center_pos_y;
- float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
- width /= screen_w;
- float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
- height /= screen_h;
-
- if (color.getAlpha() < 255)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- {
- glDisable(GL_BLEND);
- }
-
- if (clip)
- {
- if (!clip->isValid())
- return;
-
- glEnable(GL_SCISSOR_TEST);
- const core::dimension2d& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
- glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
- clip->getWidth(), clip->getHeight());
- }
-
- glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
- glBindVertexArray(SharedObject::UIVAO);
- UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- if (clip)
- glDisable(GL_SCISSOR_TEST);
- glUseProgram(0);
-
- glGetError();
-}
-
-bool hasGLExtension(const char* extension)
+bool hasGLExtension(const char* extension)
{
if (glGetStringi != NULL)
{
diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp
index 3477b649b..631fc4cf2 100644
--- a/src/graphics/glwrap.hpp
+++ b/src/graphics/glwrap.hpp
@@ -15,78 +15,7 @@ namespace HardwareStats
}
void initGL();
-GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
video::ITexture* getUnicolorTexture(const video::SColor &c);
-void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
-GLuint LoadShader(const char * file, unsigned type);
-
-template
-void loadAndAttach(GLint ProgramID)
-{
- return;
-}
-
-template
-void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
-{
- GLint ShaderID = LoadShader(filepath, ShaderType);
- glAttachShader(ProgramID, ShaderID);
- glDeleteShader(ShaderID);
- loadAndAttach(ProgramID, args...);
-}
-
-template
-void printFileList()
-{
- return;
-}
-
-template
-void printFileList(GLint ShaderType, const char *filepath, Types ... args)
-{
- Log::error("GLWrapp", filepath);
- printFileList(args...);
-}
-
-enum AttributeType
-{
- OBJECT,
- PARTICLES_SIM,
- PARTICLES_RENDERING,
-};
-
-void setAttribute(AttributeType Tp, GLuint ProgramID);
-
-template
-GLint LoadProgram(AttributeType Tp, Types ... args)
-{
- GLint ProgramID = glCreateProgram();
- loadAndAttach(ProgramID, args...);
- if (irr_driver->getGLSLVersion() < 330)
- setAttribute(Tp, ProgramID);
- glLinkProgram(ProgramID);
-
- GLint Result = GL_FALSE;
- int InfoLogLength;
- glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
- if (Result == GL_FALSE) {
- Log::error("GLWrapp", "Error when linking these shaders :");
- printFileList(args...);
- glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
- char *ErrorMessage = new char[InfoLogLength];
- glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
- Log::error("GLWrapp", ErrorMessage);
- delete[] ErrorMessage;
- }
-
- GLenum glErr = glGetError();
- if (glErr != GL_NO_ERROR)
- {
- Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
- }
-
- return ProgramID;
-}
class GPUTimer;
@@ -132,30 +61,74 @@ public:
void BlitToDefault(size_t, size_t, size_t, size_t);
};
-// core::rect needs these includes
-#include
+class VertexUtils
+{
+public:
+ static void bindVertexArrayAttrib(enum video::E_VERTEX_TYPE tp)
+ {
+ switch (tp)
+ {
+ case video::EVT_STANDARD:
+ // Position
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
+ // Normal
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
+ // Color
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
+ // Texcoord
+ glEnableVertexAttribArray(3);
+ glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
+ break;
+ case video::EVT_2TCOORDS:
+ // Position
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
+ // Normal
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
+ // Color
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
+ // Texcoord
+ glEnableVertexAttribArray(3);
+ glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
+ // SecondTexcoord
+ glEnableVertexAttribArray(4);
+ glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
+ break;
+ case video::EVT_TANGENTS:
+ // Position
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
+ // Normal
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
+ // Color
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
+ // Texcoord
+ glEnableVertexAttribArray(3);
+ glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
+ // Tangent
+ glEnableVertexAttribArray(5);
+ glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
+ // Bitangent
+ glEnableVertexAttribArray(6);
+ glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
+ break;
+ }
+ }
+};
+
#include "utils/vec3.hpp"
#include "texturemanager.hpp"
void draw3DLine(const core::vector3df& start,
const core::vector3df& end, irr::video::SColor color);
-void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
- const core::rect& destRect,
- const core::rect& sourceRect, const core::rect* clipRect,
- const video::SColor &colors, bool useAlphaChannelOfTexture);
-
-void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect& destRect,
- const irr::core::rect& sourceRect, const irr::core::rect* clipRect,
- const irr::video::SColor &color, bool useAlphaChannelOfTexture);
-
-void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect& destRect,
- const irr::core::rect& sourceRect, const irr::core::rect* clipRect,
- const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
-
-void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect& position,
- const irr::core::rect* clip = 0);
-
bool hasGLExtension(const char* extension);
const std::string getGLExtensions();
void getGLLimits(HardwareStats::Json *json);
diff --git a/src/graphics/hit_sfx.cpp b/src/graphics/hit_sfx.cpp
index 53800b28c..1a1f45c58 100644
--- a/src/graphics/hit_sfx.cpp
+++ b/src/graphics/hit_sfx.cpp
@@ -27,13 +27,13 @@ HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
: HitEffect()
{
m_sfx = SFXManager::get()->createSoundSource( explosion_sound );
- m_sfx->position(coord);
+ m_sfx->setPosition(coord);
// in multiplayer mode, sounds are NOT positional (because we have
// multiple listeners) so the sounds of all AIs are constantly heard.
// Therefore reduce volume of sounds.
float vol = race_manager->getNumLocalPlayers() > 1 ? 0.5f : 1.0f;
- m_sfx->volume(vol);
+ m_sfx->setVolume(vol);
m_sfx->play();
} // HitSFX
@@ -42,10 +42,7 @@ HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
*/
HitSFX::~HitSFX()
{
- if (m_sfx->getStatus() == SFXManager::SFX_PLAYING)
- m_sfx->stop();
-
- SFXManager::get()->deleteSFX(m_sfx);
+ m_sfx->deleteSFX();
} // ~HitEffect
//-----------------------------------------------------------------------------
@@ -56,7 +53,7 @@ HitSFX::~HitSFX()
void HitSFX::setPlayerKartHit()
{
if(race_manager->getNumLocalPlayers())
- m_sfx->volume(1.0f);
+ m_sfx->setVolume(1.0f);
} // setPlayerKartHit
//-----------------------------------------------------------------------------
@@ -67,7 +64,6 @@ void HitSFX::setPlayerKartHit()
*/
bool HitSFX::updateAndDelete(float dt)
{
- SFXManager::SFXStatus status = m_sfx->getStatus();
- if(status==SFXManager::SFX_INITIAL) return false;
- return status!= SFXManager::SFX_PLAYING;
+ SFXBase::SFXStatus status = m_sfx->getStatus();
+ return status!= SFXBase::SFX_PLAYING;
} // updateAndDelete
diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp
index cc654f9c9..84fececbb 100644
--- a/src/graphics/irr_driver.cpp
+++ b/src/graphics/irr_driver.cpp
@@ -22,6 +22,7 @@
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
+#include "graphics/2dutils.hpp"
#include "graphics/hardware_skinning.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"
@@ -2279,7 +2280,7 @@ void IrrDriver::RTTProvider::setupRTTScene(PtrVector& mesh,
node->setAnimationSpeed(0);
node->updateAbsolutePosition();
node->setScale( mesh_scale[n].toIrrVector() );
- //std::cout << "(((( set frame " << model_frames[n] << " ))))\n";
+ //Log::info("RTTProvider::setupRTTScene", "Set frame %d", model_frames[n]);
}
}
diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp
index d633a8a3c..7a4ddca5f 100644
--- a/src/graphics/material.cpp
+++ b/src/graphics/material.cpp
@@ -57,8 +57,7 @@ Material::Material(const XMLNode *node, bool deprecated)
m_shader_type = SHADERTYPE_SOLID;
m_deprecated = deprecated;
- node->get("name", &m_texname);
-
+ node->get("name", &m_texname);
if (m_texname=="")
{
throw std::runtime_error("[Material] No texture name specified "
@@ -66,6 +65,7 @@ Material::Material(const XMLNode *node, bool deprecated)
}
init();
+ node->get("lazy-load", &m_lazy_load);
bool b = false;
node->get("clampu", &b); if (b) m_clamp_tex |= UCLAMP; //blender 2.4 style
@@ -412,10 +412,10 @@ Material::Material(const std::string& fname, bool is_full_path,
*/
void Material::init()
{
+ m_lazy_load = false;
+ m_texture = NULL;
m_clamp_tex = 0;
m_shader_type = SHADERTYPE_SOLID;
- //m_lightmap = false;
- //m_adjust_image = ADJ_NONE;
m_backface_culling = true;
m_high_tire_adhesion = false;
m_below_surface = false;
@@ -455,6 +455,9 @@ void Material::init()
//-----------------------------------------------------------------------------
void Material::install(bool is_full_path, bool complain_if_not_found)
{
+ // Don't load a texture that is lazily loaded.
+ if(m_lazy_load) return;
+
const std::string &full_path = is_full_path
? m_texname
: file_manager->searchTexture(m_texname);
@@ -643,14 +646,14 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) con
if (speed < 0) speed = -speed;
// If we paused it due to too low speed earlier, we can continue now.
- if (sfx->getStatus() == SFXManager::SFX_PAUSED)
+ if (sfx->getStatus() == SFXBase::SFX_PAUSED)
{
if (speedplay();
}
- else if (sfx->getStatus() == SFXManager::SFX_PLAYING)
+ else if (sfx->getStatus() == SFXBase::SFX_PLAYING)
{
if (speed m_sfx_max_speed)
{
- sfx->speed(m_sfx_max_pitch);
+ sfx->setSpeed(m_sfx_max_pitch);
return;
}
float f = m_sfx_pitch_per_speed*(speed-m_sfx_min_speed) + m_sfx_min_pitch;
- sfx->speed(f);
+ sfx->setSpeed(f);
} // setSFXSpeed
//-----------------------------------------------------------------------------
diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp
index 4e95e648b..934c3c433 100644
--- a/src/graphics/material.hpp
+++ b/src/graphics/material.hpp
@@ -22,13 +22,11 @@
#include "utils/no_copy.hpp"
+#include
#include